反射

邮差的信 提交于 2020-02-07 19:55:03

反射的概念及演示

1).什么是“反射”:它是Java提供的一种技术,这种技术可以让我们任意的加载某个类,并创建它的对象,甚至不用知道这个类的名字、以及内部结构。
2).“反射”的作用:可以解开“类与类之间的耦合关系”。

运行时class文件的加载

1).当我们的程序第一次创建某个类的对象时,会去找它的class文件;如果在本次运行过程中,再创建此类对象,就不会再去找class文件了。
在这里插入图片描述
注意:JVM在运行时,为任何的类,都会在“方法区”中创建它的Class对象,而且每个类,只创建一个”Class对象”。

获取Class对象的三种方式

1).getClass()方法
2).类名.class
3).Class.forName(“全类名”);【常用】

示例代码:

public static void main(String[] args) throws ClassNotFoundException {
    //1.getClass()方法获取此类的Class对象
    Student stu1 = new Student();//创建Class对象
    Class c1 = stu1.getClass();

    //2.类名.class
    Class c2 = Student.class;//如果没有Class,会创建Class对象;如果有,就直接获取

    //3.Class.forName("全类名-带包名的类名");【常用】
    Class c3 = Class.forName("com.itheima.demo03_获取Class对象的三种方式.Student");//没有Class则创建,有则直接返回

    System.out.println(c1 == c2);//true
    System.out.println(c1 == c3);//true
}

获取构造方法并创建对象-Constructor

在Class类中,有四个方法,可以获取一个类的构造方法:
A).批量获取:【了解】
1). public Constructor[] getConstructors():获取所有的“公有”构造方法。
2). public Constructor[] getDeclaredConstructors():获取所有的构造方法,包括:公有、受保护、默认、私有。
B).单个获取:【掌握】
3). public Constructor getConstructor(Class<?>… parameterTypes):获取某个“公有”的构造方法。
4).public Constructor getDeclaredConstructor(Class<?> … parameterTypes):获取某个构造方法,可以是任何的访问权限修饰符。
创建对象:
Constructor类–> newInstance()
注意:如果没有访问权限,需要设置暴力访问:Constructor类 --> setAccessble(true)

综合示例代码:

public class Student {
    public Student(float f) {
        System.out.println("公有的、float参数的构造方法...");
    }
    public Student(){
        System.out.println("调用了公有、无参的构造方法...");
    }
    protected Student(int a){
        System.out.println("调用了受保护的、int参数的构造方法...");
    }
     Student(long a){
        System.out.println("调用了默认的、long参数的构造方法...");
    }
    private Student(String s,int a){
        System.out.println("调用了私有的、String,int参数的构造方法...");
    }

}

public class Demo {
    public static void main(String[] args) throws Exception {
        //1.获取Student的Class对象
        Class stuClass = Class.forName("com.itheima.demo04_获取构造方法并创建对象_Constructor.Student");

        //2.获取它内部的Student的构造方法
        System.out.println("获取所有公有构造方法:");
        Constructor[] cs = stuClass.getConstructors();
        System.out.println("数组长度:" + cs.length);
        for (int i = 0; i < cs.length; i++) {
            System.out.println(cs[i]);

        }
        System.out.println("获取所有构造方法,包括:公有、受保护、默认、私有:");
        Constructor[] cs2 = stuClass.getDeclaredConstructors();
        for (int i = 0; i < cs2.length; i++) {
            System.out.println(cs2[i]);

        }

        System.out.println("获取公有、无参构造方法:");
        Constructor ct1 = stuClass.getConstructor();
        System.out.println(ct1);

        System.out.println("获取公有、有参构造方法:");
        Constructor ct2 = stuClass.getConstructor(float.class);
        System.out.println(ct2);

        System.out.println("调用构造方法,创建对象:");
        Object obj1 = ct1.newInstance();//调用了公有、无参构造方法,创建了一个Student对象

        System.out.println("调用构造方法,创建对象:");
        Object obj2 = ct2.newInstance(1.72F);//由于要调用带参的构造方法,必须要传递实参

        System.out.println("获取私有构造方法:");
        Constructor ct3 = stuClass.getDeclaredConstructor(String.class, int.class);
        ct3.setAccessible(true);//设置:暴力访问
        Object obj3 = ct3.newInstance("张三", 20);


    }
}

正常示例代码:

public class Demo {
    public static void main(String[] args) throws Exception {
        //1.获取它的Class
        Class stuClass = Class.forName("com.itheima.demo04_获取构造方法并创建对象_Constructor.Student");

        //2.获取它的私有构造方法
        Constructor ct1 = stuClass.getDeclaredConstructor(String.class, int.class);
        //3.设置暴力访问
        ct1.setAccessible(true);
        //4.调用此构造方法,创建对象
        Object obj1 = ct1.newInstance("张三", 20);

    }
}

获取成员属性并赋值和取值-Field

A).批量获取:【了解】
1).public Field[] getFields():获取所有“公有”成员属性。
2).public Field[] getDeclaredFields():获取所有成员属性,包括:公有、受保护、默认、私有。
B).单个获取:
3).public Field getField(String fieldName):获取某个“公有”成员属性。
4).public Field getDeclaredField(String fieldName):获取某个成员属性,可以是公有、受保护、默认、私有。
为成员属性赋值:
Field类 --> set(Object 目标对象,Object 值)

示例代码:

public class Student {
    public String name;
    private int age;


    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        //1.获取Class
        Class stuClass = Class.forName("com.itheima.demo05_获取成员属性并赋值和取值_Field.Student");

        System.out.println("获取公有name属性:");
        Field nameField = stuClass.getField("name");
        System.out.println(nameField);

        System.out.println("獲取私有的age属性:");
        Field ageField = stuClass.getDeclaredField("age");
        ageField.setAccessible(true);//设置:暴力访问
        System.out.println(ageField);

        //要操作两个属性,必须先创建对象
        Object obj1 = stuClass.getConstructor().newInstance();
        Object obj2 = stuClass.getConstructor().newInstance();

        System.out.println(obj1);
        System.out.println(obj2);

        //为第一个对象的属性赋值为:刘德华,18
        //以前:对象.属性 = 值;
        //反射:属性Field对象.set(目标对象,值)

        nameField.set(obj1, "刘德华");
        ageField.set(obj1, 18);
        //为第二个对象的属性赋值为:成龙,30
        nameField.set(obj2, "成龙");
        ageField.set(obj2, 30);


        System.out.println(obj1);
        System.out.println(obj2);
    }
}

获取成员方法并调用-method

A).批量获取:【了解】
1).public Method[] getMethods():获取所有“公有”成员方法。
2).public Method[] getDeclaredMethods():获取所有成员方法,包括:公有、受保护、默认、私有。
B).单个获取:
3).public Method getMethod(String methodName,Class … paramtTypes):获取某个“公有”成员方法。
4).public Method getDeclaredMethod(String methodName,Class … parametTypes):获取某个成员方法,可以是公有、受保护、默认、私有。
调用方法:
Method类 --> invoke(Object 目标对象,Object … 实参列表)
注意:如果没有访问权限,要设置暴力访问:Method类的–> setAccessible(true)
示例代码:

public class Student {
    public void show1(){
        System.out.println("调用了公有的show1()...");
    }
    private int show2(String name){
        System.out.println("调用了私有的show2(),参数name = " + name);
        return 120;
    }
}

 public class Demo06 {
    public static void main(String[] args) throws Exception {
        //1.获取Class
        Class stuClass = Class.forName("com.itheima.demo06_获取成员方法并调用_method.Student");

        System.out.println("获取公有的show1()");
        Method show1Method = stuClass.getMethod("show1");
        //有访问权限的,也可以设置暴力访问,但没有必要。
        System.out.println(show1Method);

        System.out.println("获取私有的show2():");
        Method show2Method = stuClass.getDeclaredMethod("show2", String.class);
        show2Method.setAccessible(true);//设置暴力访问
        System.out.println(show2Method);

        //2.要调用方法,必须先创建对象
        Object obj = stuClass.getConstructor().newInstance();

        //3.调用show1
        show1Method.invoke(obj);//invoke()内部会去调用show1()
        //4.调用show2
        Object result = show2Method.invoke(obj, "刘德华");//invoke()内部会去调用show2()
        System.out.println("返回值:" + result);
    }
}

反射练习

实现步骤:
1).创建一个配置文件:demo01.txt;
2).写测试类:反射加载配置文件中配置的类;
3).编写一个Student类,并配置到配置文件中。
4).运行测试类,反射加载Student类,并创建对象,调用方法。

配置文件内容:
className = com.itheima.Student
methodName = study

实现代码:

public class Student {
    public void study(){
        System.out.println("我在学习Java,我的目标是月薪过万!");
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        //1.获取Class对象
        String className = getValue("className");//String className = "com.itheima.demo07_反射练习.Student"
        Class aClass = Class.forName(className);//forName("com.itheima.demo07_反射练习.Student")

        //2.获取方法对象
        Method methodName = aClass.getDeclaredMethod(getValue("methodName"));

        //3.要调用方法,先创建对象
        Object obj = aClass.getConstructor().newInstance();

        //4.调用方法[无参,无返回值]
        methodName.invoke(obj);

    }

    public static String getValue(String key) {
        Properties pro = new Properties();
        try (FileReader in = new FileReader("demo01.txt")) {
            pro.load(in);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return pro.getProperty(key);

    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!