队列和环形队列

Pix4dmapper航测教程——进阶内业处理

  返回  

反射的概念和基本使用方法

2021/8/20 18:13:17 浏览:

目录

反射

获取Class类对象的三种方式

一、反射获取构造方法对象的方法

二、反射获取成员变量的方法

三、反射获取成员方法的方法

反射的案例

一、越过泛型检查

二、通过反射运行配置文件中指定类的指定方法

总结

反射


概念:在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。

简单来说,就是在程序运行状态中,能够获取到这个类的所有属性和方法(包括私有属性、方法以及构造器),这种动态获取信息以及动态调用对象方法的功能就称为反射机制。通过反射,可以获取到类中的任何东西。

获取Class类对象的三种方式

  • 类名.class属性

  • 对象名.getClass()方法

  • Class.forName(全类名)方法

案例:

//学生类
public class Student {
    //成员变量:一个私有,一个默认,一个公共
    private String name;
    int age;
    public String address;

    //构造方法:一个私有,一个默认,两个公共
    public Student() {
    }

    private Student(String name) {
        this.name = name;
    }

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法:一个私有,四个公共
    private void function() {
        System.out.println("function");
    }

    public void method1() {
        System.out.println("method");
    }

    public void method2(String s) {
        System.out.println("method:" + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
//在这里使用的是上述自定义的Student类,其实可以是任意类
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        //使用类的class属性来获取该类对应的Class对象
        Class<Student> c1 = Student.class;
        System.out.println(c1);
        Class<Student> c2 = Student.class;
        System.out.println(c1 == c2);
        System.out.println("-----------");

        //调用对象的getClass()方法,返回该对象所属类对应的Class对象
        Student s = new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c1 == c3);
        System.out.println("-----------");

        //使用Class类中的静态方法forName(String className)
        Class<?> c4 = Class.forName("com.test.Student");
        System.out.println(c1 == c4);
    }
}

界面展示:

一、反射获取构造方法对象的方法

方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回单个构造方法对象

Constructor类用于创建对象的方法:

T newInstance(Object...initargs)根据指定的构造方法创建对象

 案例:

//使用的是上述自定义的Student类
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.test.Student");

        //返回反映由该Class对象表示的类声明的所有构造函数的Constructor对象的数组
        Constructor<?>[] cons = c.getDeclaredConstructors();
        for (Constructor con : cons){
            System.out.println(con);
        }
        System.out.println("-------------");

        //Constructor<T> getConstructor(Class<?>... parameterTypes)
        // 返回一个 Constructor对象,该对象反映由该Class对象表示的类的指定公共构造函数
        Constructor<?> con = c.getConstructor();

        //Constructor提供了一个类的单个构造函数的信息和访问权限
        //T newInstance(Object... initargs)使用由此Constructor对象表示的构造函数,
        Object obj = con.newInstance();
        System.out.println(obj);
    }
}

界面展示:

注意事项:

  • 基本数据类型也可以通过.class得到对应的Class类型

  • public void setAccessible(boolean flag):值为true,取消访问检查,访问私有时使用 (暴力反射)

二、反射获取成员变量的方法

方法名说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象

Field类用于给成员变量赋值的方法:

void set(Object obj,Object value)给obj对象的成员变量赋值为value

案例:

//使用的是上述自定义的Student类
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.test.Student");

        //Field[] getDeclaredFields() 返回一个Field对象的数组,反映了由该Class对象表示的类或接口声明的所有字段
        Field[] fields = c.getDeclaredFields();
        for(Field field : fields) {
            System.out.println(field);
        }
        System.out.println("--------");

        //Field getField(String name) 返回一个Field对象,该对象反映由该Class对象表示的类或接口的指定公共成员字段
        Field addressField = c.getField("address");

        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //Field提供有关类或接口的单个字段的信息和动态访问
        //void set(Object obj, Object value)将指定的对象参数中由此Field对象表示的字段设置为指定的新值
        addressField.set(obj,"西安"); //给obj的成员变量addressField赋值为西安
        System.out.println(obj);
    }
}

界面展示:

三、反射获取成员方法的方法

方法名说明
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象

Method类用于执行方法的方法:

Object invoke(Object obj,Object... args)调用obj对象的成员方法,参数是args,返回值是Object类型

案例:

//使用的是上述自定义的Student类
public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<?> c = Class.forName("com.test.Student");

        //Method[] getDeclaredMethods() 返回一个包含方法对象的数组,方法对象反映由Class对象表示的类或接口的所有声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承方法
        Method[] methods = c.getDeclaredMethods();
        for(Method method : methods) {
            System.out.println(method);
        }
        System.out.println("--------");

        //Method getMethod(String name, Class<?>... parameterTypes) 返回一个方法对象,该对象反映由该Class对象表示的类或接口的指定公共成员方法
        Method m = c.getMethod("method1");

        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //在类或接口上提供有关单一方法的信息和访问权限
        //Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此方法对象表示的基础方法
        //Object:返回值类型,obj:调用方法的对象,args:方法需要的参数
        m.invoke(obj);
    }
}

界面展示:

反射的案例


一、越过泛型检查

代码实现:通过反射技术,向一个泛型为Integer的集合中添加一些字符串数据

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //创建集合
        ArrayList<Integer> array = new ArrayList<Integer>();

        //获取Class类对象
        Class<? extends ArrayList> c = array.getClass();
        //获取ArrayList中的add方法
        Method m = c.getMethod("add", Object.class);

        //赋值
        m.invoke(array,"hello");
        m.invoke(array,"world");
        m.invoke(array,"java");

        System.out.println(array);
    }
}

界面展示:

二、通过反射运行配置文件中指定类的指定方法

代码实现:

class文件的设计:

//学生类
public class Student {
    public void study(){
        System.out.println("好好学习,天天向上!");
    }
}
//老师类
public class Teacher {
    public void teach(){
        System.out.println("用爱成就每一位学员!");
    }
}
public class ReflectTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //文件中的内容读到集合
        Properties prop = new Properties();
        FileReader fr = new FileReader("idea_test_9\\class.txt");
        prop.load(fr);
        fr.close();

        //获取集合中的数据
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        //通过反射使用
        Class<?> c = Class.forName(className);

        //指定构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //获取成员方法
        Method m = c.getMethod(methodName);
        //调用成员方法
        m.invoke(obj);
    }
}

界面展示:

总结


        反射部分的主要方法就介绍到这里了,可以发现反射的使用比较特殊,所实现的功能也是之前看似不可能实现的。这正是反射的强大之处,在此博主只是学习到了该部分的皮毛知识,对于具体的操作以及运用还需慢慢研究,学习是一个持续的过程,加油,为了更好的明天而战!

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号