[Class类的应用]反射的理解

一.什么是反射

Java 源码编译后生成 .class 字节码文件,类加载时会被 JVM 读取并加载到内存。在首次使用时,JVM 会为每个加载到内存的类生成唯一的 Class 对象,它是 .class 字节码在内存中的 "映射",包含了类的完整元数据(字段、方法、构造器、修饰符等)。结合Method/Field/Constructor 等反射工具类,在运行时动态获取类的元数据、调用类的成员,从而实现对类的间接操作。

二.反射解决的问题

反射机制是Java中用于解决在运行时获取类型(要求运行时这个类必须存在),然后用这个类型的Class对象来创建这个类对象,调用方法等操作。

Java 反射(Reflection)是 Java 语言的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息,而无需在编译时知道它们的名称。

三.Class对象有哪些

四.Class类

4.0 up自己做的图

4.1.怎么获取Class对象

4.2.coding

复制代码
@Test
    public void testStringClass()throws Exception{
        //获取String类的Class对象
//       (1)类名.class
        Class c1 = String.class;
//       (2)对象.getClass()
        Class c2 = "hello".getClass();
//      (3)Class.forName("类的全名称")
        Class c3 =  Class.forName("java.lang.String");
//                - 类加载器.loadClass("类的全名称")
        Class c4 =  ClassLoader.getSystemClassLoader().loadClass("java.lang.String");

        System.out.println(c1 == c2);
        System.out.println(c1 == c3);
        System.out.println(c1 == c4);
        //上面是4种方式来获取同一种类型String的Class,在JVM中只有唯一的一个Class对象代表String类型。
    }

4.3.Class类的方法

方法 作用
public boolean isArray() 判断该 Class 对象是否代表一个数组类
public boolean isInterface() 判断该 Class 对象是否代表一个接口
public boolean isPrimitive() 判断该 Class 对象是否代表基本数据类型(如 intboolean
public boolean isEnum() 判断该 Class 对象是否代表一个枚举类
public boolean isAnnotation() 判断该 Class 对象是否代表一个注解类型
public String getName() 获取类的全限定名(如 java.lang.String
public String getSimpleName() 获取类的简单名称(如 String
public Class<? super T> getSuperclass() 获取该类的父类 Class 对象
public Class<?>[] getInterfaces() 获取该类实现的所有接口 Class 对象数组

Class类的成员获取

方法 作用
public Field getField(String name) 获取指定 public 字段
public Field[] getFields() 获取所有 public 字段(含父类)
public Field getDeclaredField(String name) 获取当前类中任意权限的指定字段
public Field[] getDeclaredFields() 获取当前类中所有字段(不含父类)
public Method getMethod(String name, Class<?>... parameterTypes) 获取指定 public 方法
public Method[] getMethods() 获取所有 public 方法(含父类)
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取当前类中任意权限的指定方法
public Method[] getDeclaredMethods() 获取当前类中所有方法(不含父类)
public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取指定 public 构造器
public Constructor<?>[] getConstructors() 获取所有 public 构造器
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取当前类中任意权限的指定构造器
public Constructor<?>[] getDeclaredConstructors() 获取当前类中所有构造器

4.4利用Class类和Constuctor创建对象

4.4.1无参构造(用的多!推荐!)

复制代码
@Test
public void testUseNoArgConstructorCreateObject() throws Exception{    //用的多,推荐!(建议每个类都保留无参构造)因为创建对象要简化,后面赋值成员有别的方法
    Class<?> clazz = Class.forName("bean.Employee");

    //获取无参构造
    Constructor<?> noArgConstructor = clazz.getConstructor();
    Object obj = noArgConstructor.newInstance();

    /*//获取有参构造
    Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
    //利用有参构造创建对象
    Object obj = constructor.newInstance("Tom",18,5000);*/

    System.out.println(obj);
}

4.4.2 有参构造

复制代码
@Test
public void testUseArgsConstructorCreateObject() throws Exception{
    Class<?> clazz = Class.forName("bean.Employee");

    /*//获取无参构造
    Constructor<?> noArgConstructor = clazz.getConstructor();
    Object obj = noArgConstructor.newInstance();*/

    //获取有参构造
    Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
    //利用有参构造创建对象
    Object obj = constructor.newInstance("Tom",18,5000);

    System.out.println(obj);
}

4.5通过某个类的Class对象来操作属性

复制代码
 @Test
public void testAssignAttribute()throws Exception{
    Class<?> clazz = Class.forName("bean.Employee");

    //获取无参构造
    Constructor<?> noArgConstructor = clazz.getConstructor();
    Object obj = noArgConstructor.newInstance();
    //System.out.println(obj);
    /*//获取有参构造
    Constructor<?> constructor = clazz.getConstructor(String.class,int.class,double.class);
    //利用有参构造创建对象
    Object obj = constructor.newInstance("Tom",18,5000);*/

    /*//获取属性的类型和名称
    Field[] fields = clazz.getDeclaredFields();

    for (Field field : fields){
        System.out.println(field.getType() + " "+ field.getName());
    }*/
    Field nameField = clazz.getDeclaredField("name");
    nameField.setAccessible(true);//因为姓名是私有属性,所以为了访问,先设置可访问性为true
    nameField.set(obj,"Tom");
    System.out.println(obj);
}

4.6通过Class和Method来操作方法

复制代码
package reflect;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class testOperateMethod {
    @Test
    public void testOperateMethod() throws Exception {
        Class<?> rect = Class.forName("bean.Rectangle");
        Constructor<?> constructor = rect.getConstructor();
        Object obj = constructor.newInstance();

        Field lengthField = rect.getDeclaredField("length");
        Field widthField = rect.getDeclaredField("width");
        lengthField.setAccessible(true);
        widthField.setAccessible(true);

        lengthField.set(obj, 10);
        widthField.set(obj, 5);
        System.out.println(obj);
        Method getAreaMethod = rect.getMethod("area");
        System.out.println(getAreaMethod.invoke(obj));

        Method perimeterMethod = rect.getMethod("perimeter");
        System.out.println(perimeterMethod.invoke(obj));
    }
}
相关推荐
2601_962097368 小时前
Python工作流实战:SpiffWorkflow深度应用与BPMN自动化指南
python·自动化·工作流·bpmn·spiffworkflow
XR1234567888 小时前
医院基础网络改造升级选型深度解析
开发语言·网络·php
reasonsummer8 小时前
【办公类-146-05】20260901《一分园、二分园四大教育》(优化版:标题excle+复制AI文字+Python占位符录入)
开发语言·数据库·c#
baopixiaoz8 小时前
BeeQuant × BeeAgent:AI驱动智能交易
大数据·人工智能·python·区块链
名字还没想好☜8 小时前
Go 标准库 flag 包实战:参数解析、子命令、自定义 Value 类型与默认值
开发语言·后端·golang·go
公爵爱学习8 小时前
无人机定点飞行-介绍
开发语言·图像处理·python·学习·线性回归·无人机
stillstream_ink8 小时前
OpenCart UI 自动化测试实战:POM 四层架构 + 失败自动截图 + 飞书通知
python·测试
databook8 小时前
Beta 分布:如何用“成功”和“失败”来预测下次尝试
python·数据挖掘·数据分析
西西弗Sisyphus8 小时前
Qt 分类导航区的实现
开发语言·qt
zhanghaha13148 小时前
Python进阶教程:27_subprocess 模块 零基础超详细教程
开发语言·python