黑马程序员技术交流社区

标题: 反射 [打印本页]

作者: 编程的梦想    时间: 2013-11-15 14:33
标题: 反射
我创建了一个student类型的对象,
package reflex;

public class Student{
        public String name;
        public int age;
        Student(String name,int age){
                this.name=name;
                this.age=age;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        public String toString(){
                return name+""+age;
        }
}

//为什么下面这段代码不能获取name属性的值呢
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

class ConstrucDemo1 {
        public static void main(String args[])throws Exception{

           //System.out.println(new Student().getClass()==new Student("wangwu",20).getClass());
                   Student s=new Student();
                   Class clazz=s.getClass();
                  Constructor con=clazz.getConstructor(String.class,int.class);
                  Student stu=(Student)con.newInstance("wangwu",34);
                  Field f1=clazz.getDeclaredField("name");
                 f1.setAccessible(true);
                 System.out.println(f1.get(s));
        }
}
不解,希望懂反射的多给点指点,

作者: lichao    时间: 2013-11-15 15:10


  1. package reflex;

  2. public class Student{    从外部调用要定义成public的
  3.         public String name;
  4.         public int age;
  5.       public  Student(String name,int age){
  6.                 this.name=name;
  7.                 this.age=age;
  8.         }
  9.         public String getName() {
  10.                 return name;
  11.         }
  12.         public void setName(String name) {
  13.                 this.name = name;
  14.         }
  15.         public int getAge() {
  16.                 return age;
  17.         }
  18.         public void setAge(int age) {
  19.                 this.age = age;
  20.         }
  21.         public String toString(){
  22.                 return name+""+age;
  23.         }
  24. }

复制代码
  1. import java.lang.reflect.Constructor;
  2. import java.lang.reflect.Field;
  3. import reflex.Student;    //由于Student类封装到了包里,这里必须引入Student.class文件
  4. public class ConstrucDemo1 {
  5.         public static void main(String args[])throws Exception{

  6.            //System.out.println(new Student().getClass()==new Student("wangwu",20).getClass());
  7.                    Student s=new Student("li",5);   由于重写了Student()方法,所以调用时必须代餐数调       用
  8.                    Class clazz=s.getClass();
  9.                   Constructor con=clazz.getConstructor(String.class,int.class);
  10.                   Student stu=(Student)con.newInstance("wangwu",34);
  11.                   Field f1=clazz.getDeclaredField("name");
  12.                  f1.setAccessible(true);
  13.                  System.out.println(f1.get(s));
  14.         }
  15. }
复制代码

作者: jttsai    时间: 2013-11-15 15:24
lichao 发表于 2013-11-15 15:10

由于重写了Student()方法,所以调用时必须代餐数调 用
不是重写了Student(),而是重载了Student(),
而且反射也不是这么用的,要建立对象就不需要反射了,也就没有意义了!
建议使用Class clazz = Class.forName("day1.Student");
用这种方法forName放入字符串,字符串为需要传入的类。
这样的反射才有意义。
作者: 编程的梦想    时间: 2013-11-15 15:53
jttsai 发表于 2013-11-15 15:24
由于重写了Student()方法,所以调用时必须代餐数调 用
不是重写了Student(),而是重载了Student(),
而且 ...

嘿嘿,就这一个问题我纠结了一天,我刚刚给调试出来了,仅仅是因为Student类的构造方法修饰符应该为public,只要这里改一下,就OK了,不过还是谢谢!
作者: 终结者    时间: 2013-11-15 15:57
第一,你下面用的是暴力反射而上面类中的字段是公有的,这是冲突的,暴力反射是针对私有字段的。有两种解决方案。1、可以将字段该为私有的。2、可以取消暴力反射,直接用普通反射即可。第二、Student类中是有参的构造函数,而你new对象的时候用的是无参的构造函数,Student类中是没有无参的构造函数的,这个也是有两种解决方案。1、在类中添加一个无参的构造函数。2、在mian方法中直接调用有参的构造函数。第三:在打印字段的值时传入的参数是错误的,通过字段中的get(obj)方法可以获取值,但是Obj对象不是s而是通过反射获得的对象,下面是给出代码
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ConstrucDemo1 {
    public static void main(String args[])throws Exception{

       //System.out.println(new Student().getClass()==new Student("wangwu",20).getClass());
               Student s=new Student();
               Class clazz=s.getClass();
              Constructor con=clazz.getConstructor(String.class,int.class);
              Student stu=(Student)con.newInstance("wangwu",34);
              Field f1=clazz.getDeclaredField("name");
           
             System.out.println(f1.get(stu));
    }
}
class Student{
        public String name;
        public int age;
        public Student(){}
        public Student(String name,int age){
                this.name=name;
                this.age=age;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        public String toString(){
                return name+""+age;
        }
}
作者: jttsai    时间: 2013-11-15 16:15
还有楼主:
你的构造函数为什么没有public啊。。。。。。。。。。。
还有二楼说的导入包也不一定,如果在同一个包下,根本不需要导入包
我的写法,希望能帮助到你
Class clazz = Class.forName("day1.Student");

                Constructor con = clazz.getConstructor(String.class, int.class);

                Student stu = (Student) con.newInstance("wangwu", 34);

                Field f1 = clazz.getDeclaredField("name");

                f1.setAccessible(true);

                System.out.println(f1.get(stu));
作者: 终结者    时间: 2013-11-15 16:48
首先还是要谢谢你的,只所以没有public我是将所有代码放在一个.java文件中的。.java文件中只允许一个类拥有public修饰符,且被修饰符修饰的类名必须和与源文件名相同。对于三种获得内存中字节码文件有所了解,我只是按照代码而进行分析的,总不能说把楼主代码改得面目全非,或者自写一个类吧,只是希望如果分析错误的话能得到你们的提醒帮我纠正




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2