[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 对象是否代表基本数据类型(如 int、boolean)
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));
    }
}
相关推荐
JWASX2 小时前
【agent 开发】Agent 智能体
大数据·人工智能·python
智购科技无人售货机工厂店3 小时前
玻璃瓶饮料破损率突然上升,排查发现是取货口缓冲垫老化了~YH
java·开发语言·人工智能·python·eclipse
JWASX3 小时前
【agent 开发】agent 开发学习 - LangChain(2)
python·学习·langchain
枫叶丹43 小时前
语音 AI 怎样边听边答:实时对话系统的工作原理
开发语言·人工智能·chatgpt·开源·php·agent·codex
xie0510_3 小时前
Any类简要实现
开发语言·c++·算法
小狼Solar3 小时前
SAP MDG 功能范围说明(基于S/4HANA 2025)
java·开发语言
kimnoic3 小时前
Python常用标准库模块及查询使用方法
开发语言·python
范中勤3 小时前
Python 与 Java:模块、包、对象、反射核心差异总结
java·python·面试·反射·元类
I Am a robert girl3 小时前
HelixWorld 源码剖析:当世界模型第一次“开口说话”
python·多模态·扩散模型·世界模型·自回归·空间音频·流式推理
棉猴3 小时前
玩游戏学Python6-演员Actor
python·pygame·玩游戏·游戏编程·actor·pgzero