Java反射是什么?

目录

反射是什么?

反射的作用是什么?

看完这个使用方法,那么可以深入理解反射的作用了(白话理解反射的作用)

这些特性有什么用

反射学什么?

反射第一步:加载类,获取类的字节码:class对象

获取类的构造器:constructor对象

这个示例演示了如何使用反射获取类的构造器。在示例中,printConstructors 和 printConstructor 方法用于打印构造器的信息。

获取类的成员变量:field对象

这个示例演示了如何使用反射获取类的成员变量。在示例中,printFields 和 printField 方法用于打印成员变量的信息

获取类的成员方法

在这个示例中,printMethods 和 printMethod 方法用于打印成员方法的信息。这样,你就能够使用反射获取类的成员方法并进行操作。

反射的注意事项

暂时对于反射就这么多,后续还会继续更新

反射是什么?

反射其实是Java提供的一种方法,能够加载类,并允许以编程的方式解剖类中的各种成分(成员变量,方法,构造器(构造方法)等)     其实就是一种在运行时检查或操作类,方法,字段等程序结构的能力。(在Java中,反射机制允许程序在运行时获取类的信息,调用类的方法,访问类的字段)  

反射的作用是什么?

想要理解反射的作用你先耐心浏览一遍反射的使用步骤

  1. 获取类型信息:通过反射可以获取类,结构体,接口等类型的信息,包括成员变量,方法,属性等。这可以让你在运行时动态的了解一个对象的结构
  2. 实例化对象:使用反射可以在运行时实例化对象,即使你在编写代码时不知道要实例化的确切类型
  3. 调用方法和属性:通过反射可以在运行时调用对象的方法和访问其属性,这对于动态地调用不同类型的对象的方法或属性是很有用的
  4. 获取和设置字段值:反射也可以用于获取和设置对象的字段值,即使这些字段是私有的

也可以这样理解

  1. 获取类的信息:通过反射可以获取类的名称,父类,接口,字段和方法等信息
  2. 创建对象:通过反射可以在运行时动态地创建对象,例如根据类名创建对象等
  3. 访问和修改对象的属性:通过反射可以获取和修改对象的属性值,包括私有属性和共有属性(反射的作用:可以破坏封装性)
  4. 调用对象的方法:通过反射可以调用对象的方法,包括私有方法和公有方法
  5. 获取和操作注解:通过反射可以获取类,方法,字段等上的注解,并可以根据注解的信息来动态地调整程序行为

下面是一个简单的例子,展示在Java中如何使用反射获取类信息

import java.lang.reflect.*;

public class ReflectionExample {
    public static void main(String[] args) {
        // 获取类信息
        Class<?> clazz = String.class;
        //这里的String是一个类,这里调用class方法来获取类信息
        //<?>是范型,可以用来接收任何一个类型的对象
        System.out.println("Class Name: " + clazz.getName());

        // 获取构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println("Constructors: " + Arrays.toString(constructors));

        // 获取方法
        Method[] methods = clazz.getMethods();
        System.out.println("Methods: " + Arrays.toString(methods));

        // 实例化对象
        try {
            Object obj = clazz.newInstance();
            System.out.println("Instance: " + obj);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        //try catch可以不用看,是系统对你的方法安全性有问题,重要的就是下面这三行
        //Object obj = clazz.newInstance();
        //System.out.println("Instance: " + obj);
        //e.printStackTrace();
    }
}

看完这个使用方法,那么可以深入理解反射的作用了(白话理解反射的作用)

通常情况下,当我们写程序时,我们在编码时,我们在编码时就已经知道了类的结构,比如类的名字,属性和方法。然而,反射允许程序在运行时去“探知”,“了解”类的信息,而不是在编写代码是就知道

考虑一个简单的例子:你在一个包中写了一个类,然后你在你的程序中引入了这个包,后来别人拿到了这个这个包的源码,对这个类进行了修改,增加了几个方法,这个时候你并不知道这个类进行了修改,但是,如果你使用反射,你的程序就可以在运行时就发现这个类的新方法,并调用它们,而不需要你在编写代码时就知道这些方法的存在。(这就是反射的作用)

当你使用反射时,你的程序可以在运行时动态地探查类的结构,包括新添加的方法,字段和参数等,如果某个类的源代码被修改,添加了新的方法和参数,而你的程序在运行时就使用了反射,它仍然能够发现并调用这些新的结构

这些特性有什么用

这些特性是的反射在某些情境下非常有用,尤其是在编写通用,灵活的代码,与其他可能被修改的代码交互时。例如,一些框架和库可能需要与用户提供的插件或模块进行交互,而这些插件可能会在运行时动态地添加新的功能

反射学什么?

  1. 反射第一步:加载类,获取类的字节码:Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法:Method对象

反射第一步:加载类,获取类的字节码:class对象

序号获取方式示例
1类字面量(MyClass.class)Class clazz1 = MyClass.class;
2对象的 getClass() 方法MyClass obj = new MyClass();<br>Class clazz2 = obj.getClass();
3Class.forName() 方法(通过类的全限定名)Class clazz3 = Class.forName("com.example.MyClass");
import java.lang.reflect.*;

public class ReflectionExample {

    public static void main(String[] args) {
        // 通过类字面量获取Class对象
        Class clazz1 = MyClass.class;
        printClassInfo(clazz1);

        // 通过对象的getClass()方法获取Class对象
        MyClass obj = new MyClass();
        Class clazz2 = obj.getClass();
        printClassInfo(clazz2);

        // 通过Class.forName()方法获取Class对象
        try {
            Class clazz3 = Class.forName("MyClass");
            printClassInfo(clazz3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void printClassInfo(Class clazz) {
        System.out.println("类名: " + clazz.getName());
        System.out.println("简单类名: " + clazz.getSimpleName());
        System.out.println("是否是接口: " + clazz.isInterface());
        System.out.println("是否是数组: " + clazz.isArray());
        System.out.println("是否是基本类型: " + clazz.isPrimitive());
        System.out.println("---------------------------");

        // 获取类的字段信息
        Field[] fields = clazz.getDeclaredFields();
        System.out.println("字段信息:");
        for (Field field : fields) {
            System.out.println("字段名: " + field.getName() + ", 类型: " + field.getType().getSimpleName());
        }
        System.out.println("---------------------------");

        // 获取类的方法信息
        Method[] methods = clazz.getDeclaredMethods();
        System.out.println("方法信息:");
        for (Method method : methods) {
            System.out.println("方法名: " + method.getName() + ", 返回类型: " + method.getReturnType().getSimpleName());
        }
        System.out.println("---------------------------");

        // 获取类的构造方法信息
        Constructor[] constructors = clazz.getDeclaredConstructors();
        System.out.println("构造方法信息:");
        for (Constructor constructor : constructors) {
            System.out.println("构造方法名: " + constructor.getName());
        }
        System.out.println("===========================");
    }
}

class MyClass {
    private int age;
    public String name;

    public MyClass() {
    }

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

    public void sayHello() {
        System.out.println("Hello from MyClass!");
    }

    private void privateMethod() {
        System.out.println("This is a private method.");
    }
}

获取类的构造器:constructor对象

序号获取构造器的方法示例
1getDeclaredConstructors()Constructor[] constructors = clazz.getDeclaredConstructors();
2getDeclaredConstructor(Class<?>... parameterTypes)Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
3getConstructors()Constructor[] constructors = clazz.getConstructors();
4getConstructor(Class<?>... parameterTypes)Constructor constructor = clazz.getConstructor(String.class, int.class);
import java.lang.reflect.Constructor;

public class ConstructorExample {

    public static void main(String[] args) {
        // 获取 Class 对象
        Class<?> clazz = MyClass.class;

        // 1. 获取所有声明的构造器
        Constructor<?>[] constructors1 = clazz.getDeclaredConstructors();
        printConstructors("Declared Constructors", constructors1);

        // 2. 获取指定参数类型的声明构造器
        try {
            Constructor<?> constructor1 = clazz.getDeclaredConstructor(String.class, int.class);
            printConstructor("Declared Constructor with parameters", constructor1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 3. 获取所有公共的构造器
        Constructor<?>[] constructors2 = clazz.getConstructors();
        printConstructors("Public Constructors", constructors2);

        // 4. 获取指定参数类型的公共构造器
        try {
            Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class);
            printConstructor("Public Constructor with parameters", constructor2);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public static void printConstructors(String title, Constructor<?>[] constructors) {
        System.out.println(title + ":");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("---------------------------");
    }

    public static void printConstructor(String title, Constructor<?> constructor) {
        System.out.println(title + ":");
        System.out.println(constructor);
        System.out.println("---------------------------");
    }
}

class MyClass {
    private int age;
    public String name;

    public MyClass() {
    }

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

    public void sayHello() {
        System.out.println("Hello from MyClass!");
    }

    private void privateMethod() {
        System.out.println("This is a private method.");
    }
}

这个示例演示了如何使用反射获取类的构造器。在示例中,printConstructorsprintConstructor 方法用于打印构造器的信息。

获取类的成员变量:field对象

序号获取成员变量的方法示例
1getDeclaredFields()Field[] fields = clazz.getDeclaredFields();
2getDeclaredField(String name)Field field = clazz.getDeclaredField("fieldName");
3getFields()Field[] fields = clazz.getFields();
4getField(String name)Field field = clazz.getField("fieldName");
import java.lang.reflect.Field;

public class FieldExample {

    public static void main(String[] args) {
        // 获取 Class 对象
        Class<?> clazz = MyClass.class;

        // 1. 获取所有声明的成员变量
        Field[] fields1 = clazz.getDeclaredFields();
        printFields("Declared Fields", fields1);

        // 2. 获取指定名称的声明成员变量
        try {
            Field field1 = clazz.getDeclaredField("name");
            printField("Declared Field by Name", field1);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 3. 获取所有公共的成员变量
        Field[] fields2 = clazz.getFields();
        printFields("Public Fields", fields2);

        // 4. 获取指定名称的公共成员变量
        try {
            Field field2 = clazz.getField("name");
            printField("Public Field by Name", field2);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public static void printFields(String title, Field[] fields) {
        System.out.println(title + ":");
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("---------------------------");
    }

    public static void printField(String title, Field field) {
        System.out.println(title + ":");
        System.out.println(field);
        System.out.println("---------------------------");
    }
}

class MyClass {
    private int age;
    public String name;

    public MyClass() {
    }

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

    public void sayHello() {
        System.out.println("Hello from MyClass!");
    }

    private void privateMethod() {
        System.out.println("This is a private method.");
    }
}

这个示例演示了如何使用反射获取类的成员变量。在示例中,printFieldsprintField 方法用于打印成员变量的信息

获取类的成员方法

序号获取成员方法的方法示例
1getDeclaredMethods()Method[] methods1 = clazz.getDeclaredMethods();
2getDeclaredMethod(String name, Class<?>... parameterTypes)Method method1 = clazz.getDeclaredMethod("methodName", String.class, int.class);
3getMethods()Method[] methods2 = clazz.getMethods();
4getMethod(String name, Class<?>... parameterTypes)Method method2 = clazz.getMethod("methodName", String.class, int.class);
import java.lang.reflect.Method;

public class MethodExample {

    public static void main(String[] args) {
        // 获取 Class 对象
        Class<?> clazz = MyClass.class;

        // 1. 获取所有声明的成员方法
        Method[] methods1 = clazz.getDeclaredMethods();
        printMethods("Declared Methods", methods1);

        // 2. 获取指定名称和参数类型的声明成员方法
        try {
            Method method1 = clazz.getDeclaredMethod("sayHello");
            printMethod("Declared Method by Name", method1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 3. 获取所有公共的成员方法
        Method[] methods2 = clazz.getMethods();
        printMethods("Public Methods", methods2);

        // 4. 获取指定名称和参数类型的公共成员方法
        try {
            Method method2 = clazz.getMethod("sayHello");
            printMethod("Public Method by Name", method2);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public static void printMethods(String title, Method[] methods) {
        System.out.println(title + ":");
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("---------------------------");
    }

    public static void printMethod(String title, Method method) {
        System.out.println(title + ":");
        System.out.println(method);
        System.out.println("---------------------------");
    }
}

class MyClass {
    private int age;
    public String name;

    public MyClass() {
    }

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

    public void sayHello() {
        System.out.println("Hello from MyClass!");
    }

    private void privateMethod() {
        System.out.println("This is a private method.");
    }
}

在这个示例中,printMethodsprintMethod 方法用于打印成员方法的信息。这样,你就能够使用反射获取类的成员方法并进行操作。

反射的注意事项

虽然反射提供了修改更新程序的灵活性,但是需要注意,由于它绕过来编译时的类型检查,可能会导致一些潜在的运行时错误。比如反射能够通过一些方式获取私有方法,或者私有属性,并且对他们进行属性修改,但是其他人并不知道。

暂时对于反射就这么多,后续还会继续更新


  • 34
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值