Java反射学习笔记

一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分

反射技术用在哪里?在做框架时反射是一门不可或缺的技术。经常在配置文件中获取一个类的完整名称字符串,再创建出该类对象使用

 

要解剖一个类,首先就要得到这个类,加载这个类

Java中有个Class类用于代表某一个类的字节码

Class类既然代表某个类的字节码,它当然要提供加载某个类字节码的方法:forname().forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装

下面是加载类的三种方式:

//加载类的三种方式
//	@Test
public void addClass() throws Exception{
//方式一:
Class<Person1> clazz1 = (Class<Person1>) Class.forName("peng.Demo.Person1");
//方式二:
Class<Person1> clazz2 = Person1.class;
//方式三:
Class<Person1> clazz3 = (Class<Person1>) new Person1().getClass();
}


  加载类后,如果要new出类对象,要需要解剖出构造方法

反射构造方法:

//反射构造函数
@Test
public void reflectCon() throws Exception{
Class<Person1> clazz = (Class<Person1>) Class.forName("peng.Demo.Person1");
//无参的构造函数
/*Constructor<Person1> con = clazz.getConstructor(null);
Person1 p = con.newInstance(null);
System.out.println(p.name);*/


//另外一个new出对象的方法,只能new无参的构造函数
Person1 per = clazz.newInstance();


//     //反射出带参的构造函数
//     Constructor con = clazz.getConstructor(String.class,int.class);
//     Person1 pp = (Person1) con.newInstance("啦啦啦",123455);

//反射出私有的构造函数
Constructor con = clazz.getDeclaredConstructor(List.class);
//暴力破解
con.setAccessible(true);
Person1 person = (Person1) con.newInstance(new ArrayList());
}
  

 

 

反射类字段:

//反射字段:public String name = "aaa"
@Test
public void test01() throws Exception{
//加载类
    Class clazz = Class.forName("peng.Demo.Person1");
    Field field = clazz.getField("name");
    Person1 p = (Person1) clazz.newInstance();
    //获取字段类型
    Class type = field.getType();
    if(type.equals(String.class)){
    System.out.println(field.get(p));
    }

    //设置字段
    field.set(p, "哈哈哈哈");
    System.out.println(p.name);
    }
    //反射字段:private int age = 14
    @Test
    public void test02() throws Exception{
    Class clazz = Class.forName("peng.Demo.Person1");
    Field field = clazz.getDeclaredField("age");
    Person1 p = (Person1) clazz.newInstance();
    //获取访问权限
    field.setAccessible(true);
    System.out.println(field.get(p));
    field.set(p, 123);
    System.out.println(field.get(p));
}
    //反射字段:public static double dou = 12.21
    @Test
    public void test03() throws Exception, SecurityException{
    Class clazz = Class.forName("peng.Demo.Person1");
    Field field = clazz.getField("dou");
    Person1 p = (Person1) clazz.newInstance();
    System.out.println(field.get(p));
}    

  

 反射出类方法:

//反射:public void demo()
@Test
public void test1() throws ClassNotFoundException,     Throwable, SecurityException{
    Class clazz = Class.forName("peng.Demo.Person1");
    Person1 p = (Person1) clazz.newInstance();
    Method method = clazz.getMethod("demo", null);
    method.invoke(p, null);
}
    //反射:public void demo(String name,int password)
    @Test
    public void test2() throws Exception{
    Class clazz = Class.forName("peng.Demo.Person1");
    Person1 p = (Person1) clazz.newInstance();
    Method method = clazz.getMethod("demo",                    String.class,int.class);
    method.invoke(p, "哈哈哈",1233);

}
//反射:public Class[] demo(String name)
    @Test
    public void test3() throws Exception{
        Class clazz = Class.forName("peng.Demo.Person1");
        Person1 p = (Person1) clazz.newInstance();
    Method method = clazz.getMethod("demo", String.class);
    Class[] cls = (Class[]) method.invoke(p, "haha");
    System.out.println(cls[0]);
}
    //反射: private void demo(int password)
    @Test
    public void test4() throws Exception{
    Class clazz = Class.forName("peng.Demo.Person1");
    Person1 p = (Person1) clazz.newInstance();
    Method method = clazz.getDeclaredMethod("demo",     int.class);
    method.setAccessible(true);
    method.invoke(p, 11);
}
    @Test
    //反射:public static void demo(List list)
    public void test5() throws Exception{
    Class clazz = Class.forName("peng.Demo.Person1");
    Person1 p = (Person1) clazz.newInstance();
    Method method = clazz.getMethod("demo", List.class);
    method.invoke(p, new ArrayList());
    //其实直接通过类名访问即可
}                          

反射main方法:

  

    @Test
    public void test7() throws Exception{
        Class clazz = Class.forName("peng.Demo.Person1");
        Person1 p = (Person1) clazz.newInstance();
        Method method = clazz.getMethod("main", String[].class);
//        method.invoke(p, (Object)new String[]{"1","2"});
        //这样也行
        method.invoke(p, new Object[]{new String[]{"1","2"}});
    }

为什么要这么写?

  在JDK1.4时,invoke()方法时这样的    invoke(Object obj,Object[] os);

  当调用的方法有多个参数时,将多个参数写在一个数组中送给invoke,在调用方法时,会将该数组的参数打散,根据这些数组参数找到相对应的方法执行

  

  在JDK1.5后,可变参数出现了,在使用invoke时,可以直接写多个参数   invoke(Object obj ,Obj...o);

  为了向下兼容,如果你传递给invoke不是可变参数而是一个Object数组的话,仍旧会按照JDK1.4那样将数组打散

  我们可以把数组强转为Object,这样就不会打散了,也可以在外面再嵌套一个数组,这样打散后里面的数组就能正常成为参数正常进行调用了

注意:只有Object数组才会打散,基本数据类型数组是不会的

posted on 2014-03-11 22:46  为了这个家  阅读(176)  评论(0)    收藏  举报

导航