Java反射

目录

什么是反射?

反射我们要学习什么?

获取class对象的三种方式

获取构造器

获取成员变量

获取类方法

反射的作用:

反射的应用:


什么是反射?

java反射通俗来讲就是解剖类,并允许以编程的方式解剖类中的各个成分(构造器,成员变量,方法)。

反射我们要学习什么?

获取类的信息,并操作他们

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

第二步:获取类的构造器:Constructor对象

第三步:获取类的成员变量:Field对象

第四步:获取类的成员方法:Method对象

获取class对象的三种方式

  • 类名.class
  • 调用class提供方法:public static class forName(String package); //package为全类名
  • Object提供的方法:public Class getClass(); Class c = 对象.getClass();
public static void main(String[] args) throws Exception {
        Student stu = new Student();
        //第一种方式,类名.的方式
        Class<Student> studentClass = Student.class;
        //通过类对象,获得类名
        String simpleName = studentClass.getSimpleName();
        //通过类对象,获取全类名
        String name = studentClass.getName();

        //第二种方式,调用Class提供的方法
        Class studentClass2 = Class.forName("com.example.com.yunlong.test4.Student");

        //第三种方式,Object提供的方法:public Class getClass();
        Class studentClass3 = stu.getClass();
    }

获取构造器

第一步:获取class对象

第二步:通过 Class 对象,我们可以获取构造器信息。

  • getConstructors():获取全部的公共构造器。
  • getDeclaredConstructors():获取全部的构造器,包括私有的。
  • getConstructor(Class<?>... parameterTypes):获取指定参数类型的公共构造器。
  • getDeclaredConstructor(Class<?>... parameterTypes):获取指定参数类型的所有构造器,包括私有构造器。

获取成员变量

第一步:获取class对象

第二步:通过 Class 对象,我们可以获取成员变量信息。

  • getFields():获取全部的公共字段。
  • getDeclaredFields():获取全部的字段,包括私有的。
  • getField(String name):获取指定名称的公共字段。
  • getDeclaredField(String name):获取指定名称的所有字段,包括私有字段。
import java.lang.reflect.Field;

class MyClass {
    public String publicField;
    private int privateField;

    public MyClass(String publicField, int privateField) {
        this.publicField = publicField;
        this.privateField = privateField;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建 MyClass 类的实例
        MyClass obj = new MyClass("publicValue", 123);

        // 获取 MyClass 类的 Class 对象
        Class<?> clazz = MyClass.class;

        // 获取指定名称的公共字段
        Field publicField = clazz.getField("publicField");

        // 获取指定名称的所有字段,包括私有字段
        Field privateField = clazz.getDeclaredField("privateField");

        // 设置字段的可访问性,以便访问私有字段
        privateField.setAccessible(true);

        // 获取字段的值
        Object publicValue = publicField.get(obj);
        Object privateValue = privateField.get(obj);

        // 输出字段的值
        System.out.println("Public Field Value: " + publicValue);
        System.out.println("Private Field Value: " + privateValue);
    }
}

获取类方法

第一步:获取class对象

第二步:通过 Class 对象,我们可以获取类中方法信息。

  • getMethods():获取类的全部公共方法。
  • getDeclaredMethods():获取类的全部方法,包括私有。
  • getMethod(String name, Class<?>... parameterTypes):获取指定名称和参数类型的公共方法。
  • getDeclaredMethod(String name, Class<?>... parameterTypes):获取指定名称和参数类型的所有方法,包括私有方法。
import java.lang.reflect.Method;

class MyClass {
    public void publicMethod(String param1, int param2) {
        System.out.println("Public Method: " + param1 + ", " + param2);
    }

    private void privateMethod() {
        System.out.println("Private Method");
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        // 创建 MyClass 类的实例
        MyClass obj = new MyClass();

        // 获取 MyClass 类的 Class 对象
        Class<?> clazz = MyClass.class;

        // 获取指定名称和参数类型的公共方法
        Method publicMethod = clazz.getMethod("publicMethod", String.class, int.class);

        // 获取指定名称和参数类型的所有方法,包括私有方法
        Method privateMethod = clazz.getDeclaredMethod("privateMethod");

        // 设置私有方法可访问
        privateMethod.setAccessible(true);

        // 调用公共方法
        publicMethod.invoke(obj, "param1", 123);

        // 调用私有方法
        privateMethod.invoke(obj);
    }
}

反射的作用:

基本作用:可以得到一个类的全部成分然后操作。

可以破坏封装性:因为它可以访问和操作类的私有成员,而不受java语言访问修饰符的限制

最重要的用途:适合做java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。

反射的应用:

Java 反射广泛应用于以下几个领域:

  1. 框架开发:许多框架使用反射来实现自动配置和扩展点的加载,比如 Spring 框架。
  2. 动态代理:通过反射可以动态地创建代理对象,实现 AOP(面向切面编程)等功能。
  3. 工具类编写:比如 ORM(对象关系映射)框架需要通过反射获取实体类的信息。
  4. 调试和诊断工具:通过反射可以查看类的结构信息,帮助调试和诊断问题。

实例

使用反射做一个简易版的框架

需求:对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去。

public class MyFrame {

    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("E:\\workspacelong\\Thred\\src\\data.txt",true));
        //第一步,拿到class对象
        Class<?> a = obj.getClass();
        String simpleName = a.getSimpleName();//拿到类名
        ps.println("------------"+simpleName+"-------------");
        //第二步,拿到类中成员变量
        Field[] declaredFields = a.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            //第三步,拿到成员变量的名字
            String name = declaredField.getName();
            //第四步,拿到成员变量的值,转化为String
            String value = declaredField.get(obj)+"";
            ps.println(name+"="+value);
        }
        ps.close();
    }
}

Java 反射的优缺点

尽管 Java 反射提供了强大的功能,但也存在一些优缺点:

优点:

  • 提供了灵活性和动态性,使得编程更加灵活和易扩展。
  • 可以在运行时获取类的信息,使得一些框架和工具的开发更加简便。

缺点:

  • 性能开销较大,因为反射操作是在运行时进行的,而不是编译时。
  • 降低了代码的可读性和可维护性,因为反射使得代码更加动态和难以理解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值