>  기사  >  Java의 반사 메커니즘의 원리는 무엇입니까?

Java의 반사 메커니즘의 원리는 무엇입니까?

百草
百草원래의
2023-06-21 10:53:033049검색

Java 리플렉션 메커니즘의 원리는 바이트코드 파일이 메모리에 로드될 때 jvm이 바이트코드를 분석하고 객체의 Class 객체를 생성한다는 것입니다. Class 객체를 얻으면 객체를 사용하여 객체의 속성이나 메서드 등을 설정할 수 있습니다. 리플렉션 메커니즘은 실행 상태에 있는 모든 클래스의 모든 속성과 메서드를 아는 기능입니다. 모든 개체에 대해 해당 속성과 메서드를 호출하고 동적으로 정보를 얻고 개체 메서드를 동적으로 호출할 수 있습니다.

Java의 반사 메커니즘의 원리는 무엇입니까?

이 튜토리얼의 운영 체제: Windows 10 시스템, Java 버전 19.0.1, Dell G3 컴퓨터.

1. Reflection

1.1 리플렉션 개요

Reflection 메커니즘: 실행 중인 상태에서 모든 클래스에 대해 이 클래스의 모든 속성과 메서드를 알 수 있으며 임의의 클래스를 호출할 수 있습니다. 속성 및 메소드; 동적으로 정보를 얻고 객체 메소드를 동적으로 호출하는 이 기능을 Java 언어의 반사 메커니즘이라고 합니다

이것은 다음과 같이 작동합니다: 바이트코드 파일이 메모리에 로드되면 jvm은 바이트코드를 분석한 다음 생성합니다. 객체의 Class 객체. jvm은 Class 객체에 바이트코드 파일의 모든 정보를 저장합니다. Class 객체를 얻는 한 객체를 사용하여 객체의 메소드를 호출할 수 있습니다. 다른 작업.

反射可以动态获取类的信息,进一步实现需要的功能
例如: Spring框架通过XML文件描述类的基本信息,使用反射机制动态装配对象

왜 성찰이 필요한가요?

Java 프로그램의 개체는 런타임에 두 가지 유형, 즉 컴파일 타임 유형과 런타임 유형으로 나타날 수 있습니다. 예를 들어 Person p = new Student();인 경우 이 코드 줄은 p 변수를 생성하고 변수의 컴파일 타임 유형은 Person이고 런타임 유형은 Student입니다.

때때로 프로그램은 런타임 중에 외부에서 객체를 전달받습니다. 객체의 컴파일 타임 유형은 Object이지만 프로그램은 해당 객체의 런타임 유형 메서드를 호출해야 합니다. 이를 위해서는 프로그램이 런타임에 객체와 클래스의 실제 정보를 검색해야 합니다. 이 문제를 해결하는 방법에는 두 가지가 있습니다.

첫 번째 방법은 유형의 특정 정보가 컴파일 타임과 런타임에 완전히 알려져 있다고 가정하는 것입니다. 여기서는 먼저 instanceof 연산자를 사용하여 판단한 다음 강제 유형 변환을 사용하여 런타임 유형의 변수로 변환할 수 있습니다.

두 번째 방법은 컴파일 타임에 객체와 클래스가 어떤 클래스에 속할지 예측할 수 없다는 것입니다. 프로그램은 런타임 정보에만 의존하여 객체와 클래스의 실제 정보를 검색하므로 반영이 필요합니다.

구체적으로 리플렉션 메커니즘을 통해 다음 작업을 수행할 수 있습니다.

프로그램이 실행 중일 때 리플렉션을 통해 모든 클래스의 클래스 개체를 얻을 수 있으며 이 개체를 통해 이 클래스의 정보를 볼 수 있습니다. 프로그램이 실행 중이면 리플렉션을 통해 모든 클래스의 인스턴스를 생성하고 인스턴스 멤버에 액세스할 수 있습니다.

프로그램이 실행 중일 때 클래스의 동적 프록시 클래스 또는 동적 프록시 개체가 리플렉션 메커니즘을 통해 생성될 수 있습니다.

1.2 클래스 객체를 얻는 세 가지 방법

클래스 객체를 얻는 세 가지 방법이 있습니다:

Class name.class attribute

Object name.getClass() 메소드

Class.forName(전체 클래스 이름) 메소드

이 세 가지 메소드는 각각 프로그램 실행 단계와 획득 클래스 메소드 간의 관계는 다음과 같습니다.

Java의 반사 메커니즘의 원리는 무엇입니까?

1.2.1 코드 예

class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1.Class类中的静态方法forName("全类名")
        //全类名:包名 - 类名
        Class clazz1 = Class.forName("com.fanshe.Student");
        System.out.println(clazz1);
        // 2.通过class属性来获取
        Class clazz2 = Student.class;
        System.out.println(clazz2);
        // 3.利用对象的getClass方法来获取class对象
        // getClass方法是定义在Object类中.
        Student s = new Student();
        Class clazz3 = s.getClass();
        System.out.println(clazz3);
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz2 == clazz3);
    }
}
실행 결과는 다음과 같습니다.

Java의 반사 메커니즘의 원리는 무엇입니까? 세 가지 메서드 모두 이 클래스의 개체를 얻을 수 있으며 세 클래스는 동일합니다.

1.3 생성자 메서드를 얻어서 적용하는 리플렉션

1.3.1 생성자 객체를 얻기 위한 클래스 클래스 메서드

메서드 소개

Java의 반사 메커니즘의 원리는 무엇입니까?

1.3.2 코드 예시

package com.fanshe;
import java.lang.reflect.Constructor;
public class Student {
    private String name;
    private int age;
    // 私有的有参构造方法
    private Student(String name) {
        System.out.println("name的值为:" + name);
        System.out.println("private...Student的有参构造方法");
    }
    // 公共的无参构造方法
    public Student() {
        System.out.println("public...Student的无参构造方法");
    }
    // 公共的有参构造方法
    public Student(String name, int age) {
        System.out.println("name的值为:" + name + "age的值为:" + age);
        System.out.println("public...Student的有参构造方法");
    }
}
class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        System.out.println("获取所有公共构造方法对象的数组===========");
        method1();
        System.out.println("获取单个构造方法对象===========");
        method2();
        System.out.println("获取所有构造方法对象的数组===========");
        method3();
        System.out.println("获取单个构造方法对象===========");
        method4();
    }
    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        //        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):
        //                                      返回单个构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        System.out.println("String+int的构造");
        Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
        System.out.println(constructor);
        System.out.println("String的构造");
        constructor=clazz.getDeclaredConstructor(String.class);
        System.out.println(constructor);
    }
    private static void method3() throws ClassNotFoundException, NoSuchMethodException {
        //        Constructor<T> getConstructor(Class<?>... parameterTypes):
        //                                      返回单个公共构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //小括号中,一定要跟构造方法的形参保持一致.
        Constructor constructor1 = clazz.getConstructor();
        System.out.println(constructor1);
        Constructor constructor2 = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor2);
        //因为Student类中,没有只有一个int的构造,所以这里会报错.
//        Constructor constructor3 = clazz.getConstructor(int.class);
//        System.out.println(constructor3);
    }
    private static void method2() throws ClassNotFoundException {
        //        Constructor<?>[] getDeclaredConstructors():
        //                                      返回所有构造方法对象的数组
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
    private static void method1() throws ClassNotFoundException {
        //        Constructor<?>[] getConstructors():
        //                                      返回所有公共构造方法对象的数组
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
}
실행 중 결과는 다음과 같습니다.

Java의 반사 메커니즘의 원리는 무엇입니까?

1.3.3 생성자 클래스에서 객체를 생성하는 데 사용하는 메서드

메서드 소개

Java의 반사 메커니즘의 원리는 무엇입니까?

1.3.4 코드 예제

참고: private으로 수정된 멤버는 직접 사용할 경우 리플렉션을 강제로 획득하여 사용하게 되며, 접근 확인을 일시적으로 취소해야 합니다

package com.fanshe;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Student {
    private String name;
    private int age;
    // 私有的有参构造方法
    private Student(String name) {
        System.out.println("name的值为:" + name);
        System.out.println("private...Student的有参构造方法");
    }
    // 公共的无参构造方法
    public Student() {
        System.out.println("public...Student的无参构造方法");
    }
    // 公共的有参构造方法
    public Student(String name, int age) {
        System.out.println("name的值为:" + name + "age的值为:" + age);
        System.out.println("public...Student的有参构造方法");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name=&#39;" + name + &#39;\&#39;&#39; +
                ", age=" + age +
                &#39;}&#39;;
    }
}
// T newInstance(Object... initargs):根据指定的构造方法创建对象
class ReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        
        method1();
        method2();
        method3();
        method4();
    }
    private static void method4() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //获取一个私有的构造方法并创建对象
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取一个私有化的构造方法.
        Constructor constructor = clazz.getDeclaredConstructor(String.class);
        //被private修饰的成员,不能直接使用的
        //如果用反射强行获取并使用,需要临时取消访问检查
        constructor.setAccessible(true);
        //3.直接创建对象
        Student student = (Student) constructor.newInstance("zhangsan");
        System.out.println(student);
    }
    private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //简写格式
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
        Student student = (Student) clazz.newInstance();//这个方法现在已经过时了,了解一下
        System.out.println(student);
    }
    private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取构造方法对象
        Constructor constructor = clazz.getConstructor();
        //3.利用空参来创建Student的对象
        Student student = (Student) constructor.newInstance();
        System.out.println(student);
    }
    private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvocationTargetException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取构造方法对象
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        //3.利用newInstance创建Student的对象
        Student student = (Student) constructor.newInstance("杨天真", 22);
        System.out.println(student);
    }
}

실행 결과는 다음과 같습니다.

Java의 반사 메커니즘의 원리는 무엇입니까?

1.3.5 요약

클래스를 획득하는 세 가지 방법 object

: Class.forName ("전체 클래스 이름") , class name.class, object name.getClass()

생성자 개체를 내부로 가져옵니다

getConstructor (Class<?>... parameterTypes)
getDeclaredConstructor (Class<?>... parameterTypes)

공용이면 개체를 직접 생성하세요

newInstance(Object... initargs)

만약 비공개이므로 일시적으로 확인을 취소한 다음 객체를 생성해야 합니다

setAccessible(boolean)  暴力反射

1.4 反射获取成员变量并使用

1.4.1 Class类获取成员变量对象的方法

方法分类

Java의 반사 메커니즘의 원리는 무엇입니까?

1.4.2 示例代码

package com.fanshe;
import java.lang.reflect.Field;
public class Student {
    public String name;
    public int age;
    public String gender;
    private int money = 300;
    @Override
    public String toString() {
        return "Student{" +
                "name=&#39;" + name + &#39;\&#39;&#39; +
                ", age=" + age +
                ", gender=&#39;" + gender + &#39;\&#39;&#39; +
                ", money=" + money +
                &#39;}&#39;;
    }
}
class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        method1();
        method2();
        method3();
        method4();
    }
    private static void method4() throws ClassNotFoundException, NoSuchFieldException {
        //        Field getDeclaredField(String name):返回单个成员变量对象
        System.out.println("返回单个成员变量对象==================");
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取money成员变量
        Field field = clazz.getDeclaredField("money");
        //3.打印一下
        System.out.println(field);
    }
    private static void method3() throws ClassNotFoundException, NoSuchFieldException {
        //        Field getField(String name):返回单个公共成员变量对象
        System.out.println("返回单个公共成员变量对象==================");
        //想要获取的成员变量必须是真实存在的
        //且必须是public修饰的.
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取name这个成员变量
        Field field = clazz.getField("name");
        //3.打印一下
        System.out.println(field);
    }
    private static void method2() throws ClassNotFoundException {
        //        Field[] getDeclaredFields():返回所有成员变量对象的数组
        System.out.println("返回所有成员变量对象的数组==================");
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取所有的Field对象
        Field[] fields = clazz.getDeclaredFields();
        //3.遍历
        for (Field field : fields) {
            System.out.println(field);
        }
    }
    private static void method1() throws ClassNotFoundException {
        //        Field[] getFields():返回所有公共成员变量对象的数组
        System.out.println("返回所有公共成员变量对象的数组==================");
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取Field对象.
        Field[] fields = clazz.getFields();
        //3.遍历
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

运行结果如下:

Java의 반사 메커니즘의 원리는 무엇입니까?

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

方法介绍

Java의 반사 메커니즘의 원리는 무엇입니까?

1.4.4 示例代码

package com.fanshe;
import java.io.File;
import java.lang.reflect.Field;
public class Student {
    public String name;
    public int age;
    public String gender;
    private int money = 300;
    @Override
    public String toString() {
        return "Student{" +
                "name=&#39;" + name + &#39;\&#39;&#39; +
                ", age=" + age +
                ", gender=&#39;" + gender + &#39;\&#39;&#39; +
                ", money=" + money +
                &#39;}&#39;;
    }
}
class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
//        Object get(Object obj) 返回由该 Field表示的字段在指定对象上的值。
        method1();
        method2();
    }
    private static void method2() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取成员变量Field的对象
        Field field = clazz.getDeclaredField("money");
        //3.取消一下访问检查
        field.setAccessible(true);
        //4.调用get方法来获取值
        //4.1创建一个对象
        Student student = (Student) clazz.newInstance();
        //4.2获取指定对象的money的值
        Object o = field.get(student);
        //5.打印一下
        System.out.println(o);
    }
    private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        //        void set(Object obj, Object value):给obj对象的成员变量赋值为value
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取name这个Field对象
        Field fieldname = clazz.getField("name");
        Field fieldage = clazz.getField("age");
        //3.利用set方法进行赋值.
        //3.1先创建一个Student对象
        Student student = (Student) clazz.newInstance();
        //3.2有了对象才可以给指定对象进行赋值
        fieldname.set(student,"杨天真");
        fieldage.set(student,12);
        System.out.println(student);
    }
}

运行结果如下:

Java의 반사 메커니즘의 원리는 무엇입니까?

1.5 反射获取成员方法并使用

1.5.1 Class类获取成员方法对象的方法

方法分类

Java의 반사 메커니즘의 원리는 무엇입니까?

1.5.2 示例代码

package com.fanshe;
import java.lang.reflect.Method;
public class Student {
    //私有的,无参无返回值
    private void show() {
        System.out.println("私有的show方法,无参无返回值");
    }
    //公共的,无参无返回值
    public void function1() {
        System.out.println("function1方法,无参无返回值");
    }
    //公共的,有参无返回值
    public void function2(String name) {
        System.out.println("function2方法,有参无返回值,参数为" + name);
    }
    //公共的,无参有返回值
    public String function3() {
        System.out.println("function3方法,无参有返回值");
        return "aaa";
    }
    //公共的,有参有返回值
    public String function4(String name) {
        System.out.println("function4方法,有参有返回值,参数为" + name);
        return "bbb";
    }
}
class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        method1();
        method2();
        method3();
        method4();
        method5();
    }
    private static void method5() throws ClassNotFoundException, NoSuchMethodException {
        //        Method getDeclaredMethod(String name, Class<?>... parameterTypes):
//                                返回单个成员方法对象
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取一个成员方法show
        Method method = clazz.getDeclaredMethod("show");
        //3.打印一下
        System.out.println(method);
    }
    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取一个有形参的方法function2
        Method method = clazz.getMethod("function2", String.class);
        //3.打印一下
        System.out.println(method);
    }
    private static void method3() throws ClassNotFoundException, NoSuchMethodException {
        //        Method getMethod(String name, Class<?>... parameterTypes) :
//                                返回单个公共成员方法对象
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取成员方法function1
        Method method1 = clazz.getMethod("function1");
        //3.打印一下
        System.out.println(method1);
    }
    private static void method2() throws ClassNotFoundException {
        //        Method[] getDeclaredMethods():
//                                返回所有成员方法对象的数组,不包括继承的
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取Method对象
        Method[] methods = clazz.getDeclaredMethods();
        //3.遍历一下数组
        for (Method method : methods) {
            System.out.println(method);
        }
    }
    private static void method1() throws ClassNotFoundException {
        //        Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取成员方法对象
        Method[] methods = clazz.getMethods();
        //3.遍历
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

运行结果为 :

Java의 반사 메커니즘의 원리는 무엇입니까?

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

方法介绍

Java의 반사 메커니즘의 원리는 무엇입니까?

参数说明:

参数一: 用obj对象调用该方法

参数二: 调用方法的传递的参数(如果没有就不写)

返回值: 方法的返回值(如果没有就不写)

1.5.4 示例代码

package com.fanshe;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Student {
    //私有的,无参无返回值
    private void show() {
        System.out.println("私有的show方法,无参无返回值");
    }
    //公共的,无参无返回值
    public void function1() {
        System.out.println("function1方法,无参无返回值");
    }
    //公共的,有参无返回值
    public void function2(String name) {
        System.out.println("function2方法,有参无返回值,参数为" + name);
    }
    //公共的,无参有返回值
    public String function3() {
        System.out.println("function3方法,无参有返回值");
        return "aaa";
    }
    //公共的,有参有返回值
    public String function4(String name) {
        System.out.println("function4方法,有参有返回值,参数为" + name);
        return "bbb";
    }
}
class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, InvocationTargetException {
//        Object invoke(Object obj, Object... args):运行方法
//        参数一:用obj对象调用该方法
//        参数二:调用方法的传递的参数(如果没有就不写)
//        返回值:方法的返回值(如果没有就不写)
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取里面的Method对象  function4
        Method method = clazz.getMethod("function4", String.class);
        //3.运行function4方法就可以了
        //3.1创建一个Student对象,当做方法的调用者
        Student student = (Student) clazz.newInstance();
        //3.2运行方法
        Object result = method.invoke(student, "杨天真");
        //4.打印一下返回值
        System.out.println(result);
    }
}

运行结果为:

Java의 반사 메커니즘의 원리는 무엇입니까?

2.反射的应用

Java的反射机制在实际项目中应用广泛,常见的应用场景有:

使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序 ;

多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化;

面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。

위 내용은 Java의 반사 메커니즘의 원리는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.