[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));
    }
}
相关推荐
努力学编程呀(๑•ี_เ•ี๑)2 小时前
【在 IntelliJ IDEA 中切换项目 JDK 版本】
java·开发语言·intellij-idea
小镇敲码人2 小时前
深入剖析华为CANN框架下的Ops-CV仓库:从入门到实战指南
c++·python·华为·cann
island13142 小时前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
坚持就完事了2 小时前
Java中的集合
java·开发语言
摘星编程2 小时前
深入理解CANN ops-nn BatchNormalization算子:训练加速的关键技术
python
魔芋红茶2 小时前
Python 项目版本控制
开发语言·python
lili-felicity2 小时前
CANN批处理优化技巧:从动态批处理到流水线并行
人工智能·python
一个有梦有戏的人2 小时前
Python3基础:进阶基础,筑牢编程底层能力
后端·python
云小逸2 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap