Java反射

Posted 364.99°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射相关的知识,希望对你有一定的参考价值。

Java代码运行:

1.反射

反射机制——将类的各个部分封装成其他对象

反射作用——可以在程序运行过程中,操作这些对象
            可以解耦,提高程序的可扩展性

1.1 获取Class对象的方法

Class.forName("完整类名")
            将字节码文件加载进内存,返回Class对象
            多用于配置文件中——读取文件,加载类

类名.class
            通过类名的属性class获取
            多用于参数的传递

对象.getClass()
            getClass()是Object类中定义的方法
            多用于对象的获取字节码的方式

package com.study.web.reflect;

public class ReflectRole {
    public static void main(String[] args) throws Exception {
        //Class.forname("完整类名")
        Class class1 = Class.forName("com.study.web.reflect.Role");
        System.out.println(class1);
        //类名.class
        Class class2 = Role.class;
        System.out.println(class2);
        //对象.getClass()
        Role role = new Role();
        Class class3 = role.getClass();
        System.out.println(class3);

        //判断获取的三个Class对象是否相等
        System.out.print("class1 == class2 --> ");
        System.out.println(class1==class2);
        System.out.print("class2 == class3 --> ");
        System.out.println(class2==class3);
    }
}

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,三种方法中任意一种获取的Class对象都是同一个

1.2 Class功能/方法

获取成员变量

Filed[] getFields()
Field getField(String name)

Filed[] getDeclaredFields()
Filed getDeclaredField(String name)
获取构造方法

Constructor<?>[] getConstructors()
Constructor<T> getConstructors(类<?>...parameterTypes)

Constructor<T> getDeclaredConstructors(类<?>...parameterTypes)
Constructor<?>[] getDeclaredConstructors()

获取成员方法

Method[] getMethods()
Method getMethod(String name,类<?>...parameterTypes)

Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>...parameterTypes)

获取类名

String getName()


Role类


public class Role {

    private int id;
    private String name;
    public int age;
    public String gender;
    
    //构造器
    
    public Role() {
    }

    public Role(String name) {
        this.name = name;
    }

    public Role(int id) {
        this.id = id;
    }

    public Role(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
    //setter

    public void setId(int id) {
        this.id = id;
    }

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

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

    //toString

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", name='" + name + '\\'' +
                '}';
    } 
        
    //无参成员方法
    public void say(){
        System.out.println("say...");
    }
    //有参成员方法
    public void eat(String food){
        System.out.println("eat..."+food);
    }

获取成员变量

package com.study.web.reflect;

import java.lang.reflect.Field;
import java.util.Arrays;

public class ReflectRole1 {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class roleClass = Role.class;

        /*
            成员变量:
                设置值
                获取值
         */
        //Field[] getFields()——public修饰的成员变量
        Field[] fields1 = roleClass.getFields();
        System.out.println(Arrays.toString(fields1));

        //Field getField(String name)
        Field field1 = roleClass.getField("gender");

        //获取成员变量的值
        Role role = new Role();
        Object value = field1.get(role);
        System.out.println(value);

        //设置成员变量的值
        field1.set(role,"张三");
        System.out.println(role);

        //Filed[] getDeclaredFields()——获取所有的成员变量(无视修饰符)
        Field[] fields2 = roleClass.getDeclaredFields();
        System.out.println(Arrays.toString(fields2));

        //Filed getDeclaredField(String name)
        //直接访问私有的会报错
        Field field2 = roleClass.getDeclaredField("id");
        //忽略访问权限修饰符的安全检查
        field2.setAccessible(true);//暴力反射
        System.out.println(field2);
    }
}


获取构造方法

        //Constructor<T>[] getConstructors(类<?>...parameterTypes)
        Constructor constructor = roleClass.getConstructor(int.class,String.class);
        System.out.println(constructor);

        //创建对象——有参
        Object role1 = constructor.newInstance(001,"张三");
        System.out.println(role1);
        //创建对象——无参
        Object role2 = roleClass.newInstance();

获取成员方法

	        //Method getMethod(String name,类<?>...parameterTypes)
        Method say_Method = roleClass.getMethod("say");
        Method eat_Method = roleClass.getMethod("eat",String.class);
        //invoke——执行方法
        say_Method.invoke(role1);
        eat_Method.invoke(role1,"fish");

	    //Method[] getMethods()——除了类中定义的方法,还会输出Object的方法
        Method[] methods = roleClass.getMethods();
        System.out.println(Arrays.toString(methods));
        //获取方法名
        for (Method method:methods){
            String name =method.getName();
            System.out.println(name);
        }

获取类名

        //String getName()——获取类名(全类名)
        System.out.println(roleClass.getName());

2.案例

新建配置文件ReflectDemo.properties

className=com.study.web.reflect.Role
methodName1=say
methodName2=eat

反射测试类

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        /*
            不改变改类的任何代码的前提下,可以创建任意类的对象,可以执行任意方法

            方案:
                配置文件+反射

            步骤:
                将需要创建的对象的全类名和需要执行的方法定义在配置文件中
                在程序中加载读取配置文件
                创建对象
                执行方法
         */

        //1.加载配置文件

        //创建properties对象
        Properties properties = new Properties();
        /*
            加载配置文件,转换为一个集合
                获取class目录下的配置文件
         */
        ClassLoader classLoader = ReflectDemo.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("ReflectDemo.properties");
        properties.load(inputStream);

        //2.获取配置文件中定义的数据
        String className = properties.getProperty("className");
        String methodName1 = properties.getProperty("methodName1");
        String methodName2 = properties.getProperty("methodName2");

        //3.加载改类进内存
        Class clasz = Class.forName(className);
        //4.创建对象
        Object obj = clasz.newInstance();
        //5.获取方法对象
        Method method1 = clasz.getMethod(methodName1);
        Method method2 = clasz.getMethod(methodName2,String.class);
        //6.执行方法
        method1.invoke(obj);
        method2.invoke(obj,"noodle");

    }
}

以上是关于Java反射的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

反射机制入门

使用反射在外部JAR / CLASS上调用包含Hibernate事务的方法(Java EE)

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

OpenGL片段着色器不照亮场景