So, I have a weird issue.
This expression: method.invoke(target, null)
throws java.lang.IllegalArgumentException: wrong number of arguments
The problem is that this expression is deep inside hibernate (BasicPropertyAccessor$BasicGetter to be precise) and I guess it should work fine (it did until recently)
I debugged this problem in eclipse and indeed, if I (in Display view) call method.invoke(target)
or method.invoke(target, (Object[]) null)
everything works fine.
I'm sure my class has this getter and it has no arguments. So ... the question is, what the hell is going on?!
EDIT:
code in hibernate (BasicPropertyAccessor:143) :
public Object get(Object target) throws HibernateException {
try {
return method.invoke(target, null);
}
catch{ ... }
}
As Java cannot determine the type of literal null , you must explicitly inform the type of the literal null to Java. Failing to do so will result in an NullPointerException . For example, the following main method invokes the foo method with literal null .
Varargs is a short name for variable arguments. In Java, an argument of a method can accept arbitrary number of values. This argument that can accept variable number of values is called varargs. The syntax for implementing varargs is as follows: accessModifier methodName(datatype… arg) { // method body }
The varrags allows the method to accept zero or muliple arguments. Before varargs either we use overloaded method or take an array as the method parameter but it was not considered good because it leads to the maintenance problem.
Syntax of Varargs A variable-length argument is specified by three periods or dots(…). For Example, public static void fun(int ... a) { // method body } This syntax tells the compiler that fun( ) can be called with zero or more arguments. As a result, here, a is implicitly declared as an array of type int[].
When you pass a null
value to a varargs method, it could be interpreted as one of two things:
null
arraynull
.Java chooses the former unless the null
is explicitly cast to the component type of the varargs method. (It is recommended that you explicitly cast either way for clarity, you'll also get an obnoxious warning in Eclipse if you don't.)
When invoking methods with no arguments, you can either pass Method.invoke
an array with 0 elements, no extra arguments (which will result in an empty array), or a null
array:
public class MethodInvoke {
public static void noParams() {
System.out.println("noParams called");
}
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Method noParams = MethodInvoke.class.getMethod("noParams");
Object target = null;
noParams.invoke(target, new Object[0]);
noParams.invoke(target);
noParams.invoke(target, null);
noParams.invoke(target, (Object[]) null);
noParams.invoke(target, (Object) null); // wrong number of arguments
}
}
What appears to be happening is that method.invoke(target, null)
is being interpreted as method.invoke(target, (Object) null)
. That is inconsistent with how Java is supposed to behave.
Are you absolutely sure that your method has no parameters?
I also noticed that in newer version of hibernate they explicitly cast that null
to Object[]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With