If I have an array of objects which have a toString method and I print the array using a for loop (e.g.: simply array[i] to reach the objects and carry out System.out.println(array[i])) will the toString method be invoked automatically? It seems to be but I just want to check this is what is going on.
Yes, it will.
The advantage, in fact, of doing this over implicitly calling .toString() is that nulls are handled without throwing an exception. If array[i] is null, then System.out.println(array[i]) will print null where System.out.println(array[i].toString()) will throw a NullPointerException.
This is because the System.out.println(object) method calls System.out.print(object) which calls String.valueOf(object) which in turn calls object.toString().
Yes, it certainly will.
Here are some API descriptions of how println(Object) and print(Object) methods work.
println(Object)
print(Object)
Related
I was reading about println function and I came across that there is println(char[ ] x) as well as println(Object x)
https://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println(char[])
My question is that: As arrays in java are object so what is the need to specifically overload println() with char[] whereas rest arrays like int[] etc. uses the println(Object x) overloaded function.
println(Object x)
if you use it to print a char array (the char array is an object), it won't print the content but the objectClass#hashcode style. You can test it yourself to see the exact output.
Because they are implemented differently.
println(Object)
will (after checking for null, etc), call the parameter's toString() method and display the result of it.
The toString() method of an array is not useful: it will give you the array type and the hashcode of the array. So the overloaded form gives a more useful implementation in the case of a char[] parameter.
Note that, with most object types, the toString() method can be overridden (so overloading the println(...) method for every possible type is not necessary (or possible...). However, the toString() method cannot be overridden for arrays, so there is benefit to overloading println in this case.
Because it prints the char array as a string and otherwise prints in object form, and seeing the contents may be more convinient. You can try casting it to object first and see the difference.
Because print/ln(char[]) handles the actual printing of characters, toString() of the array object itself still provides the usual type+hash output, regardless of being an array of characters
char c[]={'a','b','c'};
Object o=c;
System.out.println(c);
System.out.println(c.toString());
System.out.println(o); // *
System.out.println(o.toString());
The * thing is interesting (and this is why I post at all, since the rest is already there in other answers) because it demonstrates that Java has single dispatch: the actual method to be invoked is decided in compilation time, based on the declared type of the argument(s). So it does not matter that o is a character array in runtime, in compilation time it seems to be an Object, and thus print/ln(Object) is going to be invoked for it.
NullPointerException is always a code clutterer. Need to check if every object is null safe and don't throw NPE.
I came across a situation:
public void aMethod(Employee emp){
String fullEmployeeDetailRow = "Name: "+emp.getName().getFirstName()
+"LastName :"+emp.getName().getFirstName()
+"Address:"
+emp.getAddress().getBillingAddress().getBuildingNumber().getApartmentNumber()
+" "
+emp.getAddress().getBillingAddress().getStreetName()
}
In above example there are so many possibilities of NPE. For instance in
emp.getAddress().getBillingAddress().getBuildingNumber().getApartmentNumber()
expression, call to
getAddress() or getBillingAddress() or getBuildingNumber()
any can be null and probable NPE source. So I now need to clutter my code to check if each can be null.
My Question / Thought is: is there a way in Java to CREATE a method which takes an expression and evaluate if it throws NullPointerException and if yes then return a default value, say a blank " "?
So in this case I need a method
expression=emp.getAddress().getBillingAddress().getBuildingNumber().getApartmentNumber()
String checkForNPE(expression){
try{
return expression;
}catch(NullPointerException e){
return " " // default Value
}
}
Problem is when I try to create a method like this , and pass an expression to it, Java evaluates the expression BEFORE calling the method and NPE is thrown beforehand!
How can I pass the expression to the method and ask Java to evaluate it inside method only?
You can use Optional in this situation.
Option.ofNullable(emp)
.map(e -> e.getAddress())
.map(a -> a.getBillingAddress())
.map(a -> a.getBuildingNumber())
.map(n -> n.getApartmentNumber())
.orElse("not set")
NullPointerException is always a code cluttrer.
I disagree.
Need to check if every object is null safe and don't throw NPE
That's not necessarily true. It is often the case that allowing an NPE to be thrown from your method is the most reasonable thing you can do in the event that some reference it tries to use is unexpectedly null. Certainly the standard library takes that approach in many places. The most likely reason to "need" to verify that every reference is non-null is an artificial standard imposed from outside.
My Question / Thought is , is there a way in Java to CREATE a method which takes an expression and evaluate if it throw NullPointerException and if yes then return a default value say blank " " .
I hesitate to say that it's impossible, but certainly there is no easy way to write a general-purpose method such as you describe. Java makes no provision for evaluating Java source code at runtime. Besides, what would be the point? Instead of invoking such a method, you can just execute the code inside a try block; if it throws an NPE then catch it, and handle the situation however is appropriate. There is no need to pre-test the expression.
How can I pass the expression to the method and ask Java to evaluate it inside method only?
You cannot. Or at least, Java makes no provision for it, as I already said. Whatever expression you use as a method argument is evaluated before the method is invoked, and a copy of the result is passed to the method. Again, use a try / catch directly -- pretty much anything else you could consider doing is far more complicated and more costly.
Alternatively, there are approaches such as #PeterLawrey's that make it easier and prettier to test every single reference. That's not what you asked, but perhaps it suits you.
What is the difference between plus quotes (+"") and using a "toString()" method or even explicitly casting with something like (String) myObject? Trade-offs?
myObject.toString()
vs.
myObject+""
or even vs.
(String) myObject
More specifically, is there any time using the myObj+"" method can get you into trouble?
Edited for clarity
EDIT 2:
Seems String.valueOf(myObj); is the prefered method for avoiding a null pointer. That said: Is there ever a time when the following is false?
String.valueOf(myObj).equals(myObj+"")
As of Java 7, if you want to avoid a NullPointerException, you can simply use one of these:
Objects.toString( myObject )
Objects.toString( myObject, "defaultValueWhenMyObjectIsNull" )
In all versions of Java, the first of these can also be accomplished with the following, as noted by #NobuGames in the first comment below:
String.valueOf( myObject )
The mechanisms you cite each has a flaw.
myObject.toString() // throws NullPointerException if myObject is null.
myObject+"" // Hack; impairs understandability.
(String) myObject // throws ClassCastException unless myObject is a String or null
EDIT (after question edit)
is there any time using the myObj+"" method can get you into trouble?
Yes, you can confuse other programmers. The intent of the hack is not clear. This can lead to increased cost in time, and increased risk of someone "fixing" it.
However, in terms of just the compiler, you're fine. From the Java Language Specification, section 15.18: String concatentation operator +:
If only one operand expression is of type String, then string conversion (ยง5.1.11) is performed on the other operand to produce a string at run time.
And from that cited section 5.1.11: String conversion:
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.
This second case leads to a difference that you asked about.
Is there ever a time when the following is false? String.valueOf(myObj).equals(myObj+"")
No, but there's a time when that throws a NullPointerException. When myObj is a non-null reference to an object whose toString() method returns null, then String.valueOf(myObj) will be null. Calling the equals method will throw the NullPointerException.
But I suspect you're asking whether there's ever a time the two have different values. Yes, they can have different values. Objects.toString() and String.valueOf() can return null values. The hack will always have a non-null value.
That said, returning null from toString() is somewhat bad form. The JLS acknowledges that it can happen, but the API implies that it should not. Personally, if I were concerned about this case, I would handle it in some way other than the hack.
This code:
myObject+""
Is translated by the compiler to this:
new StringBuilder().append(myObject).append("").toString()
The StringBuilder append method does a null check on the input argument, appending the text "null".
The String class has an overloaded valueOf method, so you can also do:
String.valueOf(myObject)
Which will do a null check, returning the text "null".
Casting to String is going to be highly contextual, so more than one technique may apply here. If you are expecting to directly cast to String, my advice would be to prepare for it. If there is a chance it can be null, then check for it. Or make the API promise not to hand you a null. That is, this is a separation of concerns and a layering of responsibilities.
However, IMO, any sufficiently complicated class ought to have a toString() method. It can be for debugging, or used as a property for computation, but it ought to be human readable. There are few cases where a human-readable version of the object is not warranted, in my experience.
Relying on overloading the + operator feels like a hack, yes.
Since myObject.toString() fails when myObject is null (throws a NullPointerException), it is safer to do myObject+"", since it's essentially doing String.valueOf(myObject).concat(""), which doesn't fail, but would instead result in the String "null".
However, is this a good practice? My first thought is that it seems like it might take longer to perform, since it's implicitly calling two methods, but it does help guarantee software that doesn't crash.
You certainly can do myObject+"". But as you already know, that requires some extra method invocation. That will depend upon the application you're using it in. Will that extra method invocation be a bottle-neck for the application? I guess that is rarely an issue. Or, to avoid that extra method call, you can directly use String#valueOf() method. But that would depend upon how you want to handle nulls. I would certainly not proceed normally in these circumstances. At least log a message indicating null reference.
Also, if you're already on Java 7, then you can use Objects.toString(Object) method, that handles null for you. Again, that method returns "null" for null references.
So, now it's your call. I've given you some option. You might want to throw exception, log message and proceed with "null" string, or some default string like "".
If you want that behavior, String.valueOf(myObject) gets you the same while being less hacky. But it also means that a null string and the string "null" are treated the same. It's usually better to check for null values explicitly, unless you're just print to a log or such. But in those cases, most methods take an Object reference and handle nulls for you (e.g. System.out.println, most logging frameworks, etc.)
As part of my Utils class, i have both
public static boolean isStringEmptyOrNull(String... s) {
When testing for a null condition
assertTrue(Utils.isStringEmptyOrNull(null));
I get "The argument of type null should explicitly be cast to String[] for the invocation of the varargs method isStringEmptyOrNull(String...) from type Utils. It could alternatively be cast to String for a varargs invocation" warning.
I'd rather not case anything though. This test is designed to simulate a condition where argument passed to the method is a null.
Is there a way to remove this warning without changing the signature of the method?
You should probably test both of these cases:
assertTrue(Utils.isStringEmptyOrNull(new String[] { null }));
assertTrue(Utils.isStringEmptyOrNull((String[]) null));
... although it's not clear to me why a method which sounds like it should only take a single string is taking an array of strings in the first place, to be honest.
(Is it obvious to you which of those invocations you meant without the cast? It isn't obvious to me... I'd have to look it up to check.)
If you are trying to mimic the way a client of your library function would call your code, you should take advantage of the fact that they will not call this particular method with the literal "null" (what would be the point?)
Instead, they would pass in some variable or expression. Since that's the case, you can do something like this and avoid casting:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));
You could specifically tell the compiler to ignore the warning using #SuppressWarnings("all").
Well that warning's there for a reason: when you call your method with null argument, since null is all and any type in Java (including Array), the compiler effectively will not know if you're calling the var-args method with an array or a non-array object (each of which is treated differentlly when var-args arguments are used). What you can do is annotate the method with SuppressWarnings("All") and then test for null before doing anything with the argument(s)
Change your test like so:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));
Rather curious why you use a vararg method for this in the first place though...