调用返回泛型列表类类型的对象的方法throws java.lang.IllegalArgumentException

时间:2016-06-09 02:32:51

标签: java reflection invoke

public class SpinnerItemAdapter<T extends BaseSpinnerItem> 
                                  extends BaseAdapter 
                                  implements ISpinnerItemAdapter<T> {

    private List<T> _baseSpinnerItemList;

    public List<T> getSpinnerItems() {
        return _baseSpinnerItemList;
    }
}

SpinnerItemAdapter.class.getMethod("getSpinnerItems", new Class[] {}) // ok 
 .invoke(new SpinnerItemAdapter<BaseSpinnerItem>(),null) // throws bellow exception

方法抛出'java.lang.IllegalArgumentException'异常。

为什么失败?

编辑回复:

** 不是假设的调用...(实例,任何参与者) - 3kings

 /**
 * @param receiver
 *            the object on which to call this method (or null for static methods)
 * @param args
 *            the arguments to the method
 * @return the result
 *
 * @throws NullPointerException
 *             if {@code receiver == null} for a non-static method
 * @throws IllegalAccessException
 *             if this method is not accessible (see {@link AccessibleObject})
 * @throws IllegalArgumentException
 *             if the number of arguments doesn't match the number of parameters, the receiver
 *             is incompatible with the declaring class, or an argument could not be unboxed
 *             or converted by a widening conversion to the corresponding parameter type
 * @throws InvocationTargetException
 *             if an exception was thrown by the invoked method
 */
public native Object invoke(Object receiver, Object... args)
        throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;

** 你传递一个参数(null)而getSpinnerItems()没有收到任何参数。试试.invoke(新的SpinnerItemAdapter()) - Johannes H.

 /** 
 * <p>If the method is static, the receiver argument is ignored (and may be null).
 *
 * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
 * allocating an empty array.
 *
 * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
 * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
 * the reflection machinery does not do this for you. (It couldn't, because it would be
 * ambiguous.)
 *
 */

1 个答案:

答案 0 :(得分:1)

您复制的文档ov invoke表明:

  

@throws IllegalArgumentException 如果参数数量与参数数量不匹配,则接收器与声明类不兼容,或者参数无法取消装箱或转换为扩展到相应参数类型的转换

(突出我的)

这正是您遇到问题的地方:您在null调用中将一个参数(getSpinnerItems())传递给invoke()方法,但getSpinnerItems()没有不管怎样。

SpinnerItemAdapter.class.getMethod("getSpinnerItems", new Class[] {})
    .invoke(new SpinnerItemAdapter<BaseSpinnerItem>())

Varargs参数可以为空(这将为varargs参数分配一个空数组),因此该调用将 no 参数传递给getSpinnerItems(),这就是你想要的。

编辑:在编辑问题时,您需要从文档中指出这一部分:

  

如果方法不带参数,则可以传递(Object[]) null而不是分配空数组。

但是,这不是你在通话中所做的。您正在传递null,根据自动装箱惯例将其转换为(Object) null。这等于varargs的一个参数,因此一个参数传递给getSpinnerItems()

如果您想遵循文档的推荐,那就是:

SpinnerItemAdapter.class.getMethod("getSpinnerItems", new Class[] {})
    .invoke(new SpinnerItemAdapter<BaseSpinnerItem>(), (Object[]) null)