What is the difference between "(Object)null" and "null" in Java? [duplicate] - java

This question already has answers here:
Why cast null to Object?
(4 answers)
Closed 9 years ago.
Take a look at the following example:
class nul
{
public static void main (String[] args)
{
System.out.println (String.valueOf((Object)null));
System.out.println (String.valueOf(null));
}
}
The first println writes null but the second throws a NullPointerException.
Why is only the second line worth an exception? And what is the difference between the two nulls? Is there a real null and a fake null in Java?

The first invocation will call the String.valueOf(Object) method, as you have explicitly typecasted null to Object reference. Conversely, the second one will invoke the overloaded String.valueOf(char[]) method, as char[] is more specific than Object for a null argument.
There are other overloaded versions of this method that accept primitive parameters, but those are not a valid match for a null argument.
From JLS §15.12.2:
There may be more than one such method, in which case the most
specific one is chosen. The descriptor (signature plus return type) of
the most specific method is one used at run time to perform the method
dispatch.
A method is applicable if it is either applicable by subtyping
(§15.12.2.2), applicable by method invocation conversion (§15.12.2.3),
or it is an applicable variable arity method (§15.12.2.4).
[...]
If several applicable methods have been identified during one of the
three phases of applicability testing, then the most specific one is
chosen, as specified in section §15.12.2.5.
Now check the source code of both the methods:
// This won't throw NPE for `obj == null`
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
// This will throw `NPE` for `data == null`
public static String valueOf(char data[]) {
return new String(data);
}

There are lots of overloaded String.valueOf methods in Java. Further, in Java null has any and all types so that anything (that isn't a primitive) can be null.
So, when you call (String.valueOf((Object)null) you call the valueOf method that takes an Object as use explicitly cast null to Object.
In the second example you don't explicitly cast the null to any particular type so in fact you call the valueOf method with a char[] which throws an NPE.
From the JLS §15.12.2
The second step searches the type determined in the previous step for
member methods. This step uses the name of the method and the types of
the argument expressions to locate methods that are both accessible
and applicable, that is, declarations that can be correctly invoked on
the given arguments.
There may be more than one such method, in which case the most
specific one is chosen. The descriptor (signature plus return type) of
the most specific method is one used at run time to perform the method
dispatch.
In this case char[] is more specific than Object so it is called when no explicit cast of null is made.

Although I accepted already an answer I would like to add the exact answer to the question, because the two answers concentrate on explaining the trap I walked into.
The difference between (Object)null and null is that the type of the first is forced to Object but the type of the second is not, as one could think, forced to Object. Instead it could also be an array instead of an object.
So the conclusion is: pass (Object)null instead of null as an argument to a method to be sure to get exactly the method working on objects instead of any other method working on arrays.

Related

Java implicitly calls intValue when passing Integer as argument [duplicate]

This question already has answers here:
How does auto boxing/unboxing work in Java?
(4 answers)
Closed 2 years ago.
So I came across a bug caused by following example:
I have static method
private static Foo findFoo(int id) {
//we use id here not important
}
Then I used it inside another method like
private static updateFoo(final Integer id, final String newData) {
final Foo existingData = findFoo(id);
// use existing data and update or make new
}
The problem is when updateFoo is called with null in id argument, the intValue() is implicitly called (I think) when calling findFoo(id) and causes NPE.
I thought Java enforces strong typing that prevents cases where Objects are passed to arguments when primitives are expected. Is there a general rule here when implitic calls are made? And could this be picked up by compiler/IDE and possibly enforce or warn?
This always happens if you use a wrapper class as its primitive counter-part. int cannot be null, so you must call intValue() onto the wrapper class.
You can either do a null check before calling findFoo() or just use the primitive int for updateFoo() or the wrapper class in findFoo().
I thought Java enforces strong typing that prevents cases where Objects are passed to arguments when primitives are expected.
The type of Integer fits, so its type is covered. It is just an implicite casting (unboxing) in this case which is totally fine.

Method Overloading ambiguity [duplicate]

The sample code is :
public class OverloadingTest {
public static void test(Object obj){
System.out.println("Object called");
}
public static void test(String obj){
System.out.println("String called");
}
public static void main(String[] args){
test(null);
System.out.println("10%2==0 is "+(10%2==0));
test((10%2==0)?null:new Object());
test((10%2==0)?null:null);
}
And the output is :
String called
10%2==0 is true
Object called
String called
The first call to test(null) invokes the method with String argument , which is understandable according to The Java Language Specification .
1) Can anyone explain me on what basis test() is invoked in preceding calls ?
2) Again when we put , say a if condition :
if(10%2==0){
test(null);
}
else
{
test(new Object());
}
It always invokes the method with String argument .
Will the compiler compute the expression (10%2) while compiling ? I want to know whether expressions are computed at compile time or run time . Thanks.
Java uses early binding. The most specific method is chosen at compile time. The most specific method is chosen by number of parameters and type of parameters. Number of parameters is not relevant in this case. This leaves us with the type of parameters.
What type do the parameters have? Both parameters are expressions, using the ternary conditional operator. The question reduces to: What type does the conditional ternary operator return? The type is computed at compile time.
Given are the two expressions:
(10%2==0)? null : new Object(); // A
(10%2==0)? null : null; // B
The rules of type evaluation are listed here. In B it is easy, both terms are exactly the same: null will be returned (whatever type that may be) (JLS: "If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression."). In A the second term is from a specific class. As this is more specific and null can be substituted for an object of class Object the type of the whole expression is Object (JLS: "If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.").
After the type evaluation of the expressions the method selection is as expected.
The example with if you give is different: You call the methods with objects of two different types. The ternary conditional operator always is evaluated to one type at compile time that fits both terms.
JLS 15.25:
The type of a conditional expression is determined as follows:
[...]
If one of the second and third operands is of the null type and the type of the other
is a reference type, then the type of the conditional expression is that reference
type.
[...]
So the type of
10 % 2 == 0 ? null : new Object();
is Object.
test((10%2==0)?null:new Object());
Is the same as:
Object o;
if(10%2==0)
o=null;
else
o=new Object();
test(o);
Since type of o is Object (just like the type of (10%2==0)?null:new Object()) test(Object) will be always called. The value of o doesn't matter.
Your answer is : Runtime because in runtime specify parameter is instance of String or not so in compile-time can't find this.
This is the really nice question.
Let me try to clarify your code that you have written above.
In your first method call
test(null);
In this the null will be converted into string type so calling the test(String obj), as per JLS you are convinced with the call.
In the second method call
test((10%2==0)?null:new Object());
Which is going to return the boolean "true" value. So first boolean "true" value is going to auto cast into Boolean Wrapper class object. Boolean wrapper Object is finding the best match with your new Object() option in the ternary operator. And the method calls with Object as a parameter so it calls the following method
public static void test(Object obj)
For the experiment sake you can try the following combinations then you will get better clarity.
test((10 % 2 == 0) ? new Object() : "stringObj" );
test((10 % 2 == 0) ? new Object() : null );
test((10 % 2 == 0) ? "stringObj" : null );
Finally in the last when you are calling with the following code.
test((10%2==0)?null:null);
This time again it returns as boolean "true" value, and it will again follow the same casts as explained above. But this time there is no new Object() parameter is there in your ternary operator. So it will be auto type cast into null Object. Again it follows same method call as the your first method call.
In the last when you asked for code if you put in if .. else statement. Then also the compiler doing the fair decision with the code.
if(10%2==0) {
test(null);
}
Here all the time your if condition is true and calling this code test(null). Therefore all the time it call the firsttest(String obj) method with String as parameter as explained above.
I think your problem is that you are making the wrong assumption, your expressions:
test((10%2==0)?null:new Object());
and
test((10%2==0)?null:null;
Will always call test(null), and that's why they will go through test (Object).
as #Banthar mentionend the ?: operator assigns a value to a variable first then evaluates the condition.
On the other hand, the if condition you mentioned always returns true, so the compiler will replace the whole if-else block with only the body of the if.
1) the test() method is determined by the type of the parameter at the compilation time :
test((Object) null);
test((Object)"String");
output :
Object called
Object called
2) The compiler is even smarter, the compiled code is equivalent to just :
test(null);
you can check the bytecode with javap -c:
0: aconst_null
1: invokestatic #6 // Method test:(Ljava/lang/String;)V
4: return
This is what Java Language Specifications say about the problem.
If more than one method declaration is both accessible and applicable
to a method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
This is test(String) method in your case.
And because of that if you add...
public static void test(Integer obj){
System.out.println("Ingeter called");
}
it will show compilation error -The method test(String) is ambiguous for the type OverloadingTest.
Just like JLS says:
It is possible that no method is the most specific, because there are
two or more maximally specific methods. In this case:
If all the maximally specific methods have the same signature, then:
If one of the maximally specific methods is not declared abstract, it
is the most specific method. Otherwise, all the maximally specific
methods are necessarily declared abstract. The most specific method is
chosen arbitrarily among the maximally specific methods. However, the
most specific method is considered to throw a checked exception if and
only if that exception is declared in the throws clauses of each of
the maximally specific methods. Otherwise, we say that the method
invocation is ambiguous, and a compile-time error occurs.

Obtain type from nested method call using JDT and AST

How can I infer the type of a nested method call such as:
JavaSourceFile javaSourceFile = new JavaSourceFile();
javaSourceFile.getClasses().size()
It works for normal method calls such as
javaSourceFile.getClasses()
But i would like to obtain the return type of getClasses(). This is what I do. In
ASTVisitor.visit(MethodInvocation invocation)
I want to obtain the type of the size() call. I use
Expression expression = invocation.getExpression();
if (expression != null) {
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding != null) {
Call call = new Call(invocation.getName().getFullyQualifiedName(), typeBinding.getName());
this.activeMethod.getCalls().add(call);
}
}
to obtain the type of a method invocation. But if there there is a method call as in outlined at the start I just get null. I also use
invocation.resolveMethodBinding();
afterwards if the binding couldn't be resolved using the expression.
In this example you have 2 method invocations. So your visitor will be called 2 times unless you return false.
First time you visit with this expression javaSourceFile.getClasses().size() and if you call resolveTypeBinding() you will actually get the type of size() method because it happens first.
However in your given code if your visitor was called with javaSourceFile.getClasses().size() then you are actually resolving type for javaSourceFile.getClasses(), because you used getExpression() method. (NOTE: if your visit method didn't return false it will be visited again as javaSourceFile.getClasses() (since it's method invocation as well) and then you will get type of javaSourceFile variable)
Also you said that you get null which I believe shouldn't happen if everything is set up properly (for example maybe you didn't specify classpaths/sourcepaths of some classes). Can't tell why that happens since I need full code.

Removing compiler's warning from a method call, advise needed

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...

Calling closest fitting method

As part of developing a small ScriptEngine, I reflectively call java methods. A call by the script engine gives me the object the method name and an array of arguments. To call the method I tried to resolve it with a call to Class.getMethod(name, argument types).
This however only works when the classes of the arguments and the classes expected by the Method are the same.
Object o1 = new Object();
Object out = System.out;
//Works as System.out.println(Object) is defined
Method ms = out.getClass().getMethod("println",o1.getClass());
Object o2 = new Integer(4);
//Does not work as System.out.println(Integer) is not defined
Method mo = out.getClass().getMethod("println",o2.getClass());
I would like to know if there is a "simple" way to get the right method, if possible with the closest fit for the argument types, or if I have to implement this myself.
Closest fit would be:
Object o1 = new Integer(1);
Object o2 = new String("");
getMethod(name, o1.getClass())//println(Object)
getMethod(name, o2.getClass())//println(String)
Update:
To clarify what I need:
The Script Engine is a small project I write in my free time so there are no strikt rules I have to follow. So I thought that selecting methods called from the Engine the same way the java compiler selects methods at compile time only with the dynamic type and not the static type of the Object would work.(with or without autoboxing)
This is what I first hoped that the Class.getMethod() would solve. But the Class.getMethod() requires the exact same Classes as argument types as the Method declares, using a subclass will result in a no such method Exception. This may happen for good reasons, but makes the method useless for me, as I don't know in advance which argument types would fit.
An alternate would be to call Class.getMethods() and iterate through the returned array and try to find a fitting method. This would however be complicated if I don't just want to take the first "good" method which I come across, so I hoped that there would be an existing solution which at least handles:
closest fit: If arg.getClass() ==
subclass and methods m(Superclass),
m(Subclass) then call m(Subclass)
variable arguments:
System.out.printf(String ,String...)
Support for autoboxing would be nice, too.
If a call cannot be resolved it may throw an exception ( ma(String,Object), ma(Object, String), args= String,String)
(If you made it till here, thanks for taking the time to read it:-))
As others have pointed out there is no standard method that does this, so you are going to have to implement your own overload resolution algorithm.
It would probably make sense to follow javac's overload resolution rules as closely as possible:
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#292575
You can probably ignore generics for a dynamically-typed scripting language, but you might still benefit from the bridge methods that the compiler generates automatically.
Some pitfalls to watch out for:
Class.isAssignableFrom does not know about automatic widening primitive conversions, because these are syntactic sugar implemented in the compiler; They do not occur in the VM or class hierarchy. e.g. int.class.isAssignableFrom(short.class) returns false.
Similarly Class.isAssignableFrom does not know about auto-boxing. Integer.class.isAssignableFrom(int.class) returns false.
Class.isInstance and Class.cast take an Object as an argument; You cannot pass primitive values to them. They also return an Object, so they cannot be used for unboxing ((int) new Integer(42) is legal in Java source but int.class.cast(new Integer(42)) throws an exception.)
I would suggest that you use getMethods(). It returns an array of all public methods (Method[]).
The most important thing here is:
"If the class declares multiple public member methods with the same parameter types, they are all included in the returned array."
What you will then need to do is to use the results in this array to determine which one of them (if any) are the closest match. Since what the closest match should be depends very much on your requirements and specific application, it does make sense to code it yourself.
Sample code illustrating one approach of how you might go about doing this:
public Method getMethod(String methodName, Class<?> clasz)
{
try
{
Method[] methods = clasz.getMethods();
for (Method method : methods)
{
if (methodName.equals(method.getName()))
{
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
{
Class<?> param = params[0];
if ((param == int.class) || (param == float.class) || (param == float.class))
{
//method.invoke(object, value);
return method;
}
else if (param.isAssignableFrom(Number.class))
{
return method;
}
//else if (...)
//{
// ...
//}
}
}
}
}
catch (Exception e)
{
//some handling
}
return null;
}
In this example, the getMethod(String, Class<?>) method will return a method that with only one parameter which is an int, float, double, or a superclass of Number.
This is a rudimentary implementation - It returns the first method that fits the bill. You would need to extend it to create a list of all methods that match, and then sort them according to some sort of criteria, and return the best matching method.
You can then take it even further by creating the more general getMethod(String, Class<?>) method, to handle more of the possible "close match" scenarios, and possibly even more than one paramter
HTH
Edit: As #finnw has pointed out, be careful when using Class#isAssignableFrom(Class<?> cls), due to its limitations, as I have in my sample code, testing the primitives separately from the Number objects.
AFAIK, there is no simple way to do this kind of thing. Certainly, there's nothing in the standard Java class libraries to do this.
The problem is that there is no single "right" answer. You need to consider all of your use-cases, decide what the "right method" should be and implement your reflection code accordingly.

Categories

Resources