编写java文件如下:
package org.danni.reflect_1; import java.util.ArrayList; public class ArrayListDemo { public static void main(String[] args) { //创建集合对象 ArrayList<Integer> array = new ArrayList<Integer>(); array.add(10); System.out.println(array); } }使用xJad反编译文件打开编译后的class文件,我们可以发现内容变成下面这样的了 对应的class字节码文件如下:
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://kpdus.tripod.com/jad.html // Decompiler options: packimports(3) fieldsfirst ansi space // Source File Name: ArrayListDemo.java package org.danni.reflect_1; import java.util.ArrayList; public class ArrayListDemo { public ArrayListDemo() { } public static void main(String args[]) { ArrayList array = new ArrayList(); array.add(Integer.valueOf(10)); System.out.println(array); } }我们可以发现在Class文件中,在add方法内进行了强制类型转换。而ArrayList中的泛型却不见了。可见这个泛型只是给编译器看的。 现在我们再看一下add()方法的源码:add方法中传递的必须是E类型,也就是此处的Integer类型
public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; }因此我们可以想到要想在一个ArrayList对象中插入字符串,只要获得他的class字节码文件就可以了,因为在字节码文件中是在add方法内进行了强制类型转换,所以我们传递任何类型的参数都是可以的。 要获得class字节码文件,我们自然而然也就想到了要使用反射,以为这个题目的解决答案就如下所示:
public class ArrayListDemo { public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { //创建集合对象 ArrayList<Integer> array = new ArrayList<Integer>(); //获得array对象的字节码对象,返回的结果是个Class对象 Class c = array.getClass(); //参数解释:(方法名,参数类型的class) //add(E e) :因此参数是个泛型E,也就是Object类型 Method m = c.getMethod("add", Object.class); m.invoke(array, "添加的字符串是我"); //调用array的add方法,并传入值 m.invoke(array, "再添加一个字符串呀"); System.out.println(array); } }输出:
[添加的字符串是我, 再添加一个字符串呀]