[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));
    }
}
相关推荐
for_ever_love__20 分钟前
Objective-C学习 NSSet 和 NSMutableSet 功能详解
开发语言·学习·ios·objective-c
zm-v-159304339861 小时前
Python 数据挖掘从入门到精通:回归 / 分类 / 聚类 / 关联分析完整教程
python·数据挖掘·回归
似水明俊德6 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
qq_417695057 小时前
机器学习与人工智能
jvm·数据库·python
漫随流水7 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
Thera7777 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
yy我不解释7 小时前
关于comfyui的mmaudio音频生成插件时时间不一致问题(一)
python·ai作画·音视频·comfyui
炘爚8 小时前
C语言(文件操作)
c语言·开发语言
阿蒙Amon8 小时前
C#常用类库-详解SerialPort
开发语言·c#
凸头8 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言