This is a follow-up question to some previous questions about String initialization in Java.
After some small tests in Java, I'm facing the following question:
Why can I execute this statement
String concatenated = str2 + " a_literal_string";
when str2 a String object initialized to null (String str2 = null;) but I cannot call the method toString() on str2? Then how does Java do the concatenation of a null String object and a string literal?
By the way, I tried also to concatenate an Integer initialized to null and the string literal "a_literal_string" and I've got the same thing that is "null a_literal_string" in the console. So whichever kind of null gives the same thing?
PS : System.out.println(concatenated); gives null a_literal_string as output in the console.
This line:
String concatenated = str2 + " a_literal_string";
is compiled into something like
String concatenated = new StringBuilder().append(str2)
.append(" a_literal_string")
.toString();
This gives "null a_literal_string" (and not NullPointerException) because StringBuilder.append is implemented using String.valueOf, and String.valueOf(null) returns the string "null".
I tried also to concatenate an Integer initialized to null and the string literal "a_literal_string" and I've got the same thing
This is for the same reason as above. String.valueOf(anyObject) where anyObject is null will give back "null".
Related
What is the difference between
Object foo = "something";
String bar = String.valueOf(foo);
and
Object foo = "something";
String bar = (String) foo;
Casting to string only works when the object actually is a string:
Object reallyAString = "foo";
String str = (String) reallyAString; // works.
It won't work when the object is something else:
Object notAString = new Integer(42);
String str = (String) notAString; // will throw a ClassCastException
String.valueOf() however will try to convert whatever you pass into it to a String. It handles both primitives (42) and objects (new Integer(42), using that object's toString()):
String str;
str = String.valueOf(new Integer(42)); // str will hold "42"
str = String.valueOf("foo"); // str will hold "foo"
Object nullValue = null;
str = String.valueOf(nullValue); // str will hold "null"
Note especially the last example: passing null to String.valueOf() will return the string "null".
String.valueOf(foo) invokes foo's .toString() method and assigns the result to the the bar. It is null and type safe operation.
Casting will just assign foo to the bar, if the types are matching. Otherwise, the expression will throw a ClassCastException.
Casting means that the object needs to be of type String, while String.valueOf() can take other types as well.
Both generates same output in case of String.
Casting fails in case of provided object is Not a string.
String.valueOf method is used to get the String represenation of it's parameter object.
(String) value casts object value to string.
You can use the String.valueOf method to get the String representation of an object without worrying about null references. If you try to cast String on a null reference you would get a NullPointerException.
final Object obj = null;
final String strValOfObj = String.valueOf(obj);
final String strCastOfObj = (String) obj;
if (strValOfObj == null) System.out.println("strValOfObj is null");
if (strCastOfObj == null) System.out.println("strCastOfObj is null");
Output: strCastOfObj is null
The first one i.e, String.valueOf returns a string only if the object is a representable type which is a value type or a String.. Else it throws the exception.
In the latter one, you are directly casting which can fail if the object isn't a string.
Online example.
http://ideone.com/p7AGh5
in String.valueOf(); string as work typecasting all the argument passed in valueof() method convert in String and just like integer.string() convert integer into string only
Converting the value to String in java; There are multiple ways of doing it.
Just wanted to know what's the difference between each other in the following ways.
strValue.toString()
strValue+""
""+strValue
It depends on java version. Java 7 would act a bit smarter using StringBuilder + append().
Generally, you do not want unnecessary allocations. Use first one.
strValue.toString()
will return itself, because the toString() implementation of String (I'm guessing strValue is indeed of type String) returns this.
strValue+""
""+strValue
Will result in the same value (strValue) but won't invoke the toString() method
All Strings contain the same value, try it out:
String strValue = "Hello world"; // not null
String a = strValue.toString();
String b = strValue+"";
String c = ""+strValue;
Measuring its length give all the result 11, because adding an empty String to another one equals the original String itself:
System.out.println(a.length());
...
Try the equality between these Strings:
System.out.println(a.equals(b));
System.out.println(b.equals(c));
System.out.println(c.equals(a));
They are all true, because these Strings have the same value to be compared. All it in the case the strValue is not null.
One major difference is how null is handled.
If strValue is null, strValue.toString() will throw a NullPointerException, while the other two options will return the String "null".
Other differences may be observed if strValue is of a boxed numeric type, and you try to concatenate other numeric variables to it.
For example :
If
Integer a = 5;
Integer strValue = 6;
Then
a+strValue+""
would return
"11"
while
a+""+strValue
or
""+a+strValue
would return
"56"
I want to get string values of my fields (they can be type of long string or any object),
if a field is null then it should return empty string, I did this with guava;
nullToEmpty(String.valueOf(gearBox))
nullToEmpty(String.valueOf(id))
...
But this returns null if gearbox is null! Not empty string because valueOf methdod returns string "null" which leads to errors.
Any Ideas?
EDIt: there are 100s fields I look for something easy to implement
You can use Objects.toString() (standard in Java 7):
Objects.toString(gearBox, "")
Objects.toString(id, "")
From the linked documentation:
public static String toString(Object o, String nullDefault)
Returns the result of calling toString on the first argument if the first argument is not null and returns the second argument otherwise.
Parameters:
o - an object
nullDefault - string to return if the first argument is null
Returns:
the result of calling toString on the first argument if it is not null and the second argument otherwise.
See Also:
toString(Object)
For java 8 you can use Optional approach:
Optional.ofNullable(gearBox).orElse("");
Optional.ofNullable(id).orElse("");
If you don't mind using Apache commons, they have a StringUtils.defaultString(String str) that does this.
Returns either the passed in String, or if the String is null, an empty String ("").
If you also want to get rid of "null", you can do:
StringUtils.defaultString(str).replaceAll("^null$", "")
or to ignore case:
StringUtils.defaultString(str).replaceAll("^(?i)null$", "")
If alternative way, Guava provides Strings.nullToEmpty(String).
Source code
String str = null;
str = Strings.nullToEmpty(str);
System.out.println("String length : " + str.length());
Result
0
Use an inline null check
gearBox == null ? "" : String.valueOf(gearBox);
StringUtils.defaultString(String str) Returns either the passed in String, or if the String is null, an empty String ("").
Example from java doc
StringUtils.defaultString(null) will return ""
StringUtils.defaultString("") will return ""
StringUtils.defaultString("bat") will return "bat"
Since you're using guava:
Objects.firstNonNull(gearBox, "").toString();
In Java 9+ use : Objects.requireNonNullElse (obj, defaultObj) https://docs.oracle.com/javase/9/docs/api/java/util/Objects.html#requireNonNullElse-T-T-
//-- returns empty string if obj is null
Objects.requireNonNullElse (obj, "")
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Concatenating null strings in Java
I'm just wondering if someone can explain why does the following code works the way it does:
String a = null;
String b = null;
String c = a + b;
System.out.println(c.toString());
This prints "nullnull" to the console.
I was kind of expecting that the operation + would thrown an exception or, to a lesser degree, that "c" would be null.
because that code compiles to
String c = new StringBuilder().append(a).append(b).toString();
and StringBuilder.append(a) appends the result of String.valueof(a) which is "null" if a is null
"String conversion," required by the concatenation operator, mandates that null values are to be mapped to the four characters null whenever a string representation is needed.
Spec for string conversion: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.11
Spec for string concatenation: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.18.1
When java find a null reference during the string concatenation convert it to the string "null". So "nullnull" is the right result.
Before concatenation for every object Java call
java.lang.String.valueOf(Object)
and if you look at the source code of that method you find this
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
This question already has answers here:
String concatenation with Null
(3 answers)
Closed 3 years ago.
Why does the following work? I would expect a NullPointerException to be thrown.
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
Why must it work?
The JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 "String Concatenation Operator +", leading to JLS 8, § 5.1.11 "String Conversion", requires this operation to succeed without failure:
...Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
How does it work?
Let's look at the bytecode! The compiler takes your code:
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
and compiles it into bytecode as if you had instead written this:
String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"
(You can do so yourself by using javap -c)
The append methods of StringBuilder all handle null just fine. In this case because null is the first argument, String.valueOf() is invoked instead since StringBuilder does not have a constructor that takes any arbitrary reference type.
If you were to have done s = "hello" + s instead, the equivalent code would be:
s = new StringBuilder("hello").append(s).toString();
where in this case the append method takes the null and then delegates it to String.valueOf().
Note: String concatenation is actually one of the rare places where the compiler gets to decide which optimization(s) to perform. As such, the "exact equivalent" code may differ from compiler to compiler. This optimization is allowed by JLS, Section 15.18.1.2:
To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
The compiler I used to determine the "equivalent code" above was Eclipse's compiler, ecj.
See section 5.4 and 15.18 of the Java Language specification:
String conversion applies only to the
operands of the binary + operator when
one of the arguments is a String. In
this single special case, the other
argument to the + is converted to a
String, and a new String which is the
concatenation of the two strings is
the result of the +. String conversion
is specified in detail within the
description of the string
concatenation + operator.
and
If only one operand expression is of
type String, then string conversion is
performed on the other operand to
produce a string at run time. The
result is a reference to a String
object (newly created, unless the
expression is a compile-time constant
expression (§15.28))that is the
concatenation of the two operand
strings. The characters of the
left-hand operand precede the
characters of the right-hand operand
in the newly created string. If an
operand of type String is null, then
the string "null" is used instead of
that operand.
The second line is transformed to the following code:
s = (new StringBuilder()).append((String)null).append("hello").toString();
The append methods can handle null arguments.
You are not using the "null" and therefore you don't get the exception. If you want the NullPointer, just do
String s = null;
s = s.toString() + "hello";
And I think what you want to do is:
String s = "";
s = s + "hello";
This is behavior specified in the Java API's String.valueOf(Object) method. When you do concatenation, valueOf is used to get the String representation. There is a special case if the Object is null, in which case the string "null" is used.
public static String valueOf(Object obj)
Returns the string representation of the Object argument.
Parameters:
obj - an Object.
Returns:
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.