import java.io.PrintStream;
import java.lang.reflect.*;class Person {
    public int age;    public String hairColor;    public Person(int age, String hairColor) {
        this.age = age;
        this.hairColor = hairColor;
    }
}public class ReflectionTest {    private static PrintStream out = System.out;    /**
     * This method is used to get public fields of an instanced object.
     */
    public static Object getProperty(Object obj, String fieldName) throws Exception {      
        Class ownerClass = obj.getClass();
        Field field = ownerClass.getField(fieldName);
        Object property = field.get(obj);        return property;
    }    /**
     * This method is used to set public fields of an instanced object.
     */
    public static void setProperty(Object obj, String fieldName, Object newValue) throws Exception {
        Class objClass = obj.getClass();
        Field field = objClass.getField(fieldName);
        field.set(obj, newValue);
    }    /**
     * This method is used to set public fields of an instanced object.
     */
    public static Object newInstance(String className, Object parameter[]) throws Exception {
        Class cls = Class.forName(className);
        int pLength = parameter.length;
        Class parameterTypes[] = new Class[pLength];
        for (int i = 0; i < pLength; i++) {
            parameterTypes[i] = parameter[i].getClass();
        }
        Constructor con = cls.getConstructor(parameterTypes);
        Object argList[] = new Object[pLength];
        for (int i = 0; i < pLength; i++) {
            argList[i] = parameter[i];
        }        return con.newInstance(argList);
    }    public static void main(String[] args) {
        Object parameter[] = {23, "Red"};
        try {
            Object a = newInstance("Person", parameter);
            out.println("person age is " + getProperty(a, "age"));
            setProperty(a, "age", 34);
            out.println("person age is " + getProperty(a, "age"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这段代码不能运行,关键是这里
for (int i = 0; i < pLength; i++) {
    parameterTypes[i] = parameter[i].getClass();
}
如果改成
parameterTypes[0] = int.class;
parameterTypes[1] = String.class;
就可以运行了,但这样是hard code的,有高手知道怎么获取类字面变量吗?

解决方案 »

  1.   


    关注,学习等答案帮推good luck
      

  2.   

    问题出在int和Integer的区别,
    for (int i = 0; i < pLength; i++) { 
        parameterTypes[i] = parameter[i].getClass(); 

    的方式返回的是Integer类对象,而parameterTypes[0] = int.class返回的是int对象,只要你在构造Person的时候用Integer别用int,使用代码中的方法就没问题了,即
    for (int i = 0; i < pLength; i++) { 
        parameterTypes[i] = parameter[i].getClass(); 
    }
      

  3.   

    和字面值没有关系,当你声明Object parameter[] = {23, "Red"}; 时,23已经被自动boxing为Integer,
    所以获取的class是Integer.class而不是int.class,调用方法时肯定找不到(Integer,String)的签名.也就是那个方法找不到.
    这里可以判断一下,如果Class为Integer.class,Short.class等,先try一下,找不到的话再将转换一下.
      

  4.   

    自动转换是没问题了,
    不过楼主传过去的就是一个Integer的23,(是object数组的关系,就自动编程Integer)
    再还原到int的话,不知道java能不能,有什么办法能。int的class,有一个叫isPrimitive可以和Integer的class区分开。不过反过来我估计不行,
    因为程序也不知道某个class,到底是Integer的还是int的
    另外说一下,
    楼主不想硬编码估计不行,
    因为下面这两个方法是不一样的,
    public Person(int age, String hairColor)
    public Person(String hairColor, int age)
    对于Person类是两个不同的构造函数,
    所以,如果想要动态的调用某个构造函数,
    应该取得所有的构造函数,然后再取得这些构造函数的ParameterTypes,
    然后再一个一个的对比,
    最后找到要调用的构造函数,再执行
    有一点点跑题了!
    继续等答案吧good luck
      

  5.   

    Person里的age用Integer定义就行了啊,一切不就ok了
      

  6.   

    你在声明Person这个类的构造方法时候用的是(int i, String c)
    而你在 定义 Object parameter[] = {23, "Red"};的时候,jvm自动把23封装成了Integer,
    所以在后面的:
        for (int i = 0; i < pLength; i++) {
            parameterTypes[i] = parameter[i].getClass();
        } 
    里面parameter[0].getClass()获得的是Integer.class,所以jvm寻找的是Person(Integer age, String c)
    这个构造方法,你声明的是(int i, String c),当然找不到了.
    要注意的是Integer类型jvm可以自动解封装为int型,但是Integer.class是不会被jvm认为和int.class是相同的
    所以造成 NoSuchMethodException,(java.lang.Integer, java.lang.String)
    如果你能弄明白我上面说的话,相信这个问题你很容易就能解决了.
      

  7.   

    这个问题最根本的解决方法就是在你传入参数的时候同时传入class数组.
    因为在实际调用的时候,参数由程序员控制传入的,所以它的类型也一样由程序员控制传入.其它任何地方转换都是不合理的.即你在调用 反映方法 ref时,既然你要传入new Object[]{23,"xxxx"};你就知道需要传new Class[]{int.class,String.class}而不是
    从Object动态获取.其实这也是严谨的C的做法.JAVA把人教懒了.
      

  8.   

    觉得这样做已没以意义了,引入了IOC不是更直接
      

  9.   


    不懂IOC,能介绍介绍吗?呵呵
      

  10.   

        public static Object newInstance(String className, Object ... parameter) throws Exception {
            Class cls = Class.forName(className);
            int pLength = parameter.length;
            Class parameterTypes[] = new Class[pLength];
            Constructor ctorlist[] = cls.getDeclaredConstructors();
            parameterTypes= ctorlist[0].getParameterTypes(); //这里还是硬编码,ctorlist[0]
            Constructor con = cls.getConstructor(parameterTypes);
            Object argList[] = new Object[pLength];
            for (int i = 0; i < pLength; i++) {
                argList[i] = parameter[i];
            }        return con.newInstance(argList);
        }
    用这个方法倒可以,但还是硬编码的,见注释。
      

  11.   


    现在不是spring很流行,里面的newInstance方法最终目的是构造一个bean,与spring applicationcontext.getBean(id)是一样的啊
            Object parameter[] = {23, "Red"};
            try {
                Object a = newInstance("Person", parameter); //这里的Person,类似于容器时的bean id
                out.println("person age is " + getProperty(a, "age"));
                setProperty(a, "age", 34);
                out.println("person age is " + getProperty(a, "age"));
            } catch (Exception e) {
                e.printStackTrace();
            }
      Object parameter[] = {23, "Red"};相当于spring容器初始注入的值,后面自己要怎么搞就怎么搞
      

  12.   

    13楼的意思是:你可以用spring的IOC来动态生成对象,根本不需要再用反映来实现
      

  13.   

    粗看了一下帖子,是不是你要getType一下在getClass
      

  14.   

    Class parameterTypes[] = new Class[pLength];
    for (int i = 0; i < pLength; i++) {
        parameterTypes[i] = parameter[i].getClass();

    这有问题吧  界限