认识和总结反射

1.问题的提出:

(1)给你一个类的全路径,比如

classPath="com.cx.Cat"

  可以根据classPath去创建实例,不能直接使用new..

(2)给一个xml配置文件,如何创建类的一个实例对象

2.反射用在什么地方?

  主要是用在框架上(struts/hibernate/spring...),如果只写普通的java程序,可以不去考虑反射。反射是java的基石。

3.(1)每个类被加载后,系统都会为该类生成一个对应的class对象,通过该class对象就可以访问到JVM中的这个类。

 (2)获得Class对象的三种方式:

    //得到Cat的Class对象(得到的是同一个对象)
    //1.通过forName
    Class clazz1=Class.forName("com.cx.reflection.Cat");
    //2.通过class属性
    Class clazz2=Cat.class;
    //3.通过Cat实例对象来获取
    Cat cat=new Cat();
    Class clazz3=cat.getClass();                            

(3)一旦获取了某个类的Class对象,程序就可以调用Class对象的方法来获得该对象和该类的真实信息了

4.通过反射生成对象有两种方式:

(1)使用Class对象的newInstance()方法,要求该Class对象的对应类有默认的构造器,java9中已废除

        Class clazz1=Class.forName("com.cx.reflection.Cat");
        //1.通过Class对象可以创建对象实例
        Cat cat1=(Cat)clazz1.newInstance();
        cat1.show();

(2)可以指定某个构造函数去创建对象

        //通过(public Cat(String name,int age))来创建实例
        Constructor c1=clazz1.getConstructor(String.class,int.class);
        Cat cat1=(Cat)c1.newInstance("小白",6);
        cat1.show();

一个容易错的例子:当构造函数的参数是数组的时候

        //通过public Cat(String [] foods)来创建实例
        Constructor c2=clazz1.getConstructor(String[].class);
        String[] foods={"鱼","老鼠"};
        c2.newInstance(foods);

问题:wrong number of arguments。

newInstance是可变参数,当传入数组时,会自动的转为c2.newInstance(foods[0],foods[1]),和构造器的形式不匹配,反射不会成功。

解决办法:将对象数组强转为一个对象

        c2.newInstance((Object)foods);

5.使用反射调用方法

        //使用反射来调用public void show()
        //cat1.show();
        Method method=clazz1.getMethod("show",null);
        //invoke的第一个参数表示对象实例,第二个参数表示给该方法传入的值
        method.invoke(cat1, null);

问题:如何去调用一个private的方法?(暴力访问)

        //如何调用私有的函数,比如private void show(String name)
        Method method4=clazz1.getDeclaredMethod("show", String.class);
        //暴力访问
        method4.setAccessible(true);
        method4.invoke(cat1, "小白");

静态方法:可以method.invoke(null, "小白");

6.使用反射访问属性值(也分为public和private)

        //使用反射访问属性值
        //Field field=clazz1.getField("name");
        Field field=clazz1.getDeclaredField("name");
        field.setAccessible(true);
        System.out.println(field.get(cat1));

 

posted on 2017-11-05 20:42  SunnyCx  阅读(149)  评论(0编辑  收藏  举报

导航