Java-反射的三种获取方式,反射的变量、方法、构造方法和作用

简介:反射(Reflection指的是允许以编程方式访问已加载类的成分(成员变量、方法、构造器等)。

一、获取反射的三种方式

        1. 反射的第一步都是先得到加载后的类,然后才可以去那类的其他成分。

        2. 获取Class类的对象的三种方式

方式一: Class c1 = Class.forName (“ 全类名 ”);
方式二: Class c2 = 类名 .class
方式三: Class c3 = 对象 . getClass ();

二、反射的构造方法

        在这里,获取Class对象的构造器作用依然是初始化一个对象返回,接下来是代码展示,并且相关代码进行了详细注解,包括获取Class对象的三种方式、获取Class对象的构造函数的相关方法以及使用Class对象的构造函数。

        首先是用做测试的Cat类,这里使用Cat类的Class对象做测试。

package com.itheima_reflect;

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

    public Cat() {
    }

    public Cat(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;
    }

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

        这是主函数,包括了详细的代码

package com.itheima_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestConstructor {
    public static void main(String[] args) throws Exception {
        /*
            以下代码演示创建Class对象的三种方法
        */
        // 获取的Class的方法一
        Class catClass = Cat.class;
        // 获取的Class的方法二
        Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
        // 获取的Class的方法三
        Cat cat = new Cat();
        Class getClass = cat.getClass();

        /*
        * 以下代码是使用反射技术获取构造器对象并使用
        */
        // 返回所有构造器对象的数组(只能拿public的)
        // 在这里需要注意,如果Class对象的其中一个构造函数是用private关键字修饰,那么这个构造函数是遍历不到的
        Constructor[] constructors = catClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
        }

        // 返回所有构造器对象的数组
        // 在这里需要注意,即使Class对象的其中一个构造函数是用private关键字修饰,也能遍历到
        Constructor[] declaredConstructors = catClass.getDeclaredConstructors();
        for (Constructor constructor : declaredConstructors) {
            // 输出Class对象中构造函数的名称和参数数量
            System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
        }

        // 返回单个构造器对象(只能拿public的)
        Constructor constructor = catClass.getConstructor();//如果不填写参数,调用Class对象的无参构造函数
        System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());

        /**
         * 以下代码展示的是使用Class对象的构造函数创建对象
         */
        // 通过newInstance()方法创建一个Cat对象
        Cat newCat = catClass.newInstance();
        // 暴力破解,如果当前catClass这个构造函数在Cat类中是私有的,那么不执行暴力破解会报错
        // public void  setAccessible(boolean flag)
        // catClass.setAccessible(boolean flag)
    }
}

三、反射的变量

        Class类中用于获取成员变量的方法,在代码中详细解释。这是主函数,包括了详细的代码(还是继续使用了Cat类)

package com.itheima_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class TestConstructor {
    public static void main(String[] args) throws Exception {
        /*
            以下代码演示创建Class对象的三种方法
        */
        // 获取的Class的方法一
        Class catClass = Cat.class;
        // 获取的Class的方法二
        Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
        // 获取的Class的方法三
        Cat cat = new Cat();
        Class getClass = cat.getClass();

        /**
         * 以下代码,展示的是如何获取Cat类的Class对象的变成员变量
         */
        // 返回所有成员变量对象的数组(只能拿public的)。在这里,因为Cat类中的成员变量都是使用private修饰的,所以数组为空
        Field[] fields = catClass.getFields();
        // 返回所有成员变量对象的数组,存在就能拿到
        Field[] declaredFields = catClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field.getName());
        }
        // 返回单个成员变量对象(只能拿public的),在这里,因为Cat类中的成员变量都是使用private修饰的,所以变量为空
        Field field = catClass.getField("name");
        // 返回单个成员变量对象,存在就能拿到
        Field declaredField = catClass.getDeclaredField("name");
    }
}

四、反射的方法

        Class类中用于获取成员方法的方法,在代码中详细解释。这是主函数,包括了详细的代码(还是继续使用了Cat类)

package com.itheima_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestConstructor {
    public static void main(String[] args) throws Exception {
        /*
            以下代码演示创建Class对象的三种方法
        */
        // 获取的Class的方法一
        Class catClass = Cat.class;
        // 获取的Class的方法二
        Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
        // 获取的Class的方法三
        Cat cat = new Cat();
        Class getClass = cat.getClass();

        /**
         * 以下代码,展示的是如何获取Cat类的Class对象的方法
         */
        // 返回所有成员方法对象的数组(只能拿public的)
        Method[] methods = catClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + "----." + method.getParameterCount() + "---->" + method.getParameterTypes());
        }
        // 返回所有成员方法对象的数组,存在就能拿到
        Method[] declaredMethods = catClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.getName() + "----." + method.getParameterCount() + "---->" + method.getParameterTypes());
        }
        // 返回单个成员方法对象(只能拿public的)
        Method method = catClass.getMethod("getName"); // 参数为要获取的方法名和以及要获取的方法参数
        // 返回单个成员方法对象,存在就能拿到
        Method getName = catClass.getDeclaredMethod("getName"); // 参数为要获取的方法名和以及要获取的方法参数
/*        // 返回所有成员变量对象的数组(只能拿public的)。在这里,因为Cat类中的成员变量都是使用private修饰的,所以数组为空
        Field[] fields = catClass.getFields();
        // 返回所有成员变量对象的数组,存在就能拿到
        Field[] declaredFields = catClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field.getName());
        }
        // 返回单个成员变量对象(只能拿public的),在这里,因为Cat类中的成员变量都是使用private修饰的,所以变量为空
        Field field = catClass.getField("name");
        // 返回单个成员变量对象,存在就能拿到
        Field declaredField = catClass.getDeclaredField("name");*/
    }
}

五、反射的作用

        在这里通过一个小案例来展示反射的功能和作用。本案例是实现一个获取运行中对象的字段数据,并且将字段名和字段值打印到指定的文件中去。

        首先是创建两个类:Student、Teacher  

package com.itheima_reflect;

public class Student {
    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;

    public Student() {
    }

    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", height=" + height +
                ", hobby='" + hobby + '\'' +
                '}';
    }
}
package com.itheima_reflect;

public class Teacher {
    private String name;
    private double salary;

    public Teacher() {
    }

    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

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

        接下来创建一个反射框架类,通过反射获取运行中对象的Class对象,通过获取的Class对象来获取相应的字段信息。 具体代码如下

package com.itheima_reflect;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    // 功能:保存任意对象的字段和相应数据到文件中去
    public static void saveObject(Object object) throws Exception {
        // 创建一个打印流,用以向文件中打印数据
        PrintStream printStream = new PrintStream(new FileOutputStream("D:\\LenovoSoftstore\\Install\\IDEA\\IDEAProject\\MyHomeTest\\src\\user.txt", true));
        // 获取object对象的Class对象
        Class aClass = object.getClass();
        String simpleName = aClass.getSimpleName();
        printStream.println("----------" + simpleName + "-------------");
        // 通过这个Class对象(aClass)获取全部字段
        Field[] fields = aClass.getDeclaredFields();
        // 遍历每一个成员变量
        for (Field field : fields) {
            // 禁止检查访问控制
            field.setAccessible(true);
            // 通过field获取字段名称
            String name = field.getName();
            // 通过field获取字段值
            String value = field.get(object) + "";
            printStream.println(name + " = " + value);
        }
        printStream.close();
    }
}

        最后是测试类,对上述功能代码进行测试。代码如下。

package com.itheima_reflect;

public class FrameTest {
    public static void main(String[] args) {
        Student student = new Student("王大宁", 18, '男', 188, "乒乓球");
        Teacher teacher = new Teacher("柳岩", 170);

        try {
            ObjectFrame.saveObject(student);
            ObjectFrame.saveObject(teacher);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

        以上就是一个通过一个小案例来展示反射的功能和作用。代码经过小猿亲测可跑。

你可能感兴趣的:(JAVA语言,java,开发语言)