Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

varargs and null argument

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:

  • method is an instance of java.lang.reflect.Method and points to the said getter
  • target is an instance of the class with public X getX() getter
  • JDK 1.6.0_31
  • code in hibernate (BasicPropertyAccessor:143) :

    public Object get(Object target) throws HibernateException {
        try {
            return method.invoke(target, null);
        }
        catch{ ... }
    }
    
like image 533
mabn Avatar asked Aug 12 '12 01:08

mabn


People also ask

Can Java Varargs be null?

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 .

What does Varargs mean?

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 }

Can Varargs take 0 arguments?

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.

What is the rule for using Varargs?

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


1 Answers

When you pass a null value to a varargs method, it could be interpreted as one of two things:

  • A null array
  • An array with one element which is null.

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

like image 61
Jeffrey Avatar answered Sep 28 '22 02:09

Jeffrey