[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));
    }
}
相关推荐
GIS阵地1 小时前
QgsRasterDataProvider 完整详解(QGIS 3.40.13 C++)
开发语言·c++·qt·开源软件·qgis
yaoxin5211232 小时前
462. Java 反射 - 获取声明类与封闭类
java·开发语言·python
阿里嘎多学长2 小时前
2026-07-14 GitHub 热点项目精选
开发语言·程序员·github·代码托管
中微极客2 小时前
解锁LLM开发全栈能力:Python + LangChain + RAG 工程实战指南
人工智能·python·langchain
hhzz2 小时前
Barbershop:基于GAN和分割Mask的图像合成技术——从理论到实战全解析
图像处理·人工智能·python·深度学习·计算机视觉
charlie1145141913 小时前
Cinux: 为大内核铺路
开发语言·c++·操作系统·现代c++
2501_914245933 小时前
C语言设计模式详解:从理论到实践的完整指南
c语言·开发语言·设计模式
Hazenix3 小时前
Go 指南:一篇文章速通 Golang
开发语言·后端·golang
灯澜忆梦3 小时前
GO_复合类型---指针
开发语言·后端·golang
Ulyanov4 小时前
雷达导引头Python仿真框架:GPU加速、6-DOF模型与半实物仿真接口
开发语言·python·雷达信号处理·雷达导引头