Java 反射四大核心类:Class、Constructor、Method、 Filed

简介: Java 反射四大核心类:Class、Constructor、Method、 Filed

反射可以做到的事情

  • 在不修改源码的情况下,通过配置文件来控制程序
  • 在程序运行的时候,通过反射动态创建对象,并且可以操作对象的所有属性、方法、构造器
  • 生成动态代理

反射重要的4个类

  • java.lang.Class
  • java.lang.reflect.Field
  • java.lang.reflect.Method
  • java.lang.reflect.Constructor

Class类

一个类在堆中只有一个Class对象,这个Class对象包含了类的完整结构信息

在使用反射的过程中,把方法、属性、构造器都当做对象来处理的

Class类对象由系统创建,继承了Object类

Class类的类图

17892935686842cb859eb5747cc090bb.png

Class类常用方法

//1.通过全路径 获取对应的Class对象
String classAllPath = "com.java.test.Student";
Class<?> cls = Class.forName(classAllPath);
//2.获取包名
String packageName = cls.getPackage().getName();
//3.获取全类名
String classFullName = cls.getName();
//4.通过Class对象创建对应对象的实例
Object obj = cls.newInstance();
//5.获取public修饰的属性,并设置值
Field nameField = cls.getField("name");
String nameValue = nameField.get(obj).toString();
nameField.set(obj,"jack");
System.out.println(nameField.get(obj)); //jack
//6.获取所有public修饰的属性(字段)
Field[] fields = cls.getFields();
for (Field field : fields) {
    System.out.println(field.getName());
}
//7.获取所有属性,包括私有属性
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
    System.out.println(declaredField.getName());
}

获取Class类对象4种方式

  • Class.forName( )
  • 类名.class
  • 对象名.getClass( )
  • 类加载器获取Class对象
//1.通过Class类的静态方法forName()获取
String classAllPath = "com.java.test.Student";
Class<?> cls = Class.forName(classAllPath);
//2.类名.class
Class<String> stringClass = String.class;
//3.对象名.getClass():通过已经创建好的对象,获取Class对象
String str = new String("hello");
Class<? extends String> aClass = str.getClass();
//4.通过类加载器来获取类的Class对象
ClassLoader classLoader = str.getClass().getClassLoader();
//ClassLoader classLoader = String.class.getClassLoader();
Class<?> strClassObject = classLoader.loadClass("java.lang.String");

基本数据类型的Class类对象和包装类的Class类对象

//byte short int long float double char boolean
Class<Byte> byteClass = byte.class;
Class<Short> shortClass = short.class;
Class<Integer> integerClass = int.class;
Class<Long> longClass = long.class;
Class<Float> floatClass = float.class;
Class<Double> doubleClass = double.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
Class<Integer> type = Integer.TYPE;
//其它包装类获取Class类对象的方式和Integer一样

Field类

  • getField( )、getFields( )、getDeclaredFields( )
  • getModifiers( ):返回修饰符
  • getType( ):返回类型
  • getName( ):返回属性名
//通过全路径 获取对应的Class对象
String classAllPath = "com.java.test.Student";
Class<?> cls = Class.forName(classAllPath);
//获取所有属性对象,包括私有属性
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
    System.out.println(declaredField.getModifiers()+" "+
            declaredField.getType()+" "+declaredField.getName());
}

Method类

  • getMethod( )、getMethods( )、getDeclaredMethods( )
  • getModifiers( ):返回方法的返回值类型
  • getParameterTypes( ):返回参数类型的数组
  • getName( ):返回方法的名称
//通过全路径 获取对应的Class对象
String classAllPath = "com.java.test.Student";
Class<?> cls = Class.forName(classAllPath);
获取所有方法对象,包括私有方法
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
    System.out.println(declaredMethod.getModifiers()+" "+declaredMethod.getReturnType()+" "+
            Arrays.toString(declaredMethod.getParameterTypes()));
}

Constructor类

  • getConstructor( )、getConstructors( )、getDeclaredConstructors( )
  • getModifiers( ):以int形式返回修饰符
  • getName( ):返回构造器的全类名
  • getParameterTypes( ):返回参数类型的数组
  • setAccessible( ):爆破,访问私有成员
  • newInstance( ):创建对象
//通过全路径 获取对应的Class对象
String classAllPath = "com.java.test.Student";
Class<?> cls = Class.forName(classAllPath);
//获取所有的构造器对象,并且获取构造器对象的信息
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println(constructor.getModifiers()+" "+constructor.getName()
            +" "+Arrays.toString(constructor.getParameterTypes()));
}
// 使用反射创建对象
// 无参构造器创建对象
Object o = cls.newInstance();
// 有参构造器创建对象
Constructor<?> constructor = cls.getConstructor(int.class, String.class);
Object o2 = constructor.newInstance(1000, "hello");
// 私有有参构造器创建对象
Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);
Object o3 = declaredConstructor.newInstance("jack");

反射的简单使用

/** 需求:
   1.根据配置文件的信息创建对象
   2.通过反射操作private修饰的属性的值,并调用对象的方法
*/

propeties配置文件

classFullPath=com.java.reflection.Student
name=jack
method=sayHello

Student类

@Data
public class Student {
    private String name;
    public void sayHello(){
        System.out.println("hello "+name);
    }
}

main( )方法

public static void main(String[] args) throws Exception {
    //1.使用Properties类读取Maven工程resources文件夹下的配置文件信息
    //1.1读取配置文件到内存中
    Properties properties = new Properties();
    InputStream resourceAsStream = DemoTest.class.getResourceAsStream("/test.properties");
    properties.load(resourceAsStream);
    //1.2获取配置文件信息
    String classFullPath = properties.get("classFullPath").toString();
    String nameProValue = properties.get("name").toString();
    String methodPro = properties.get("method").toString();
    //2.使用反射机制创建对象,并调用对象的方法和属性
    Class<?> cls = Class.forName(classFullPath); //获取运行时类对象
    Object obj = cls.newInstance();//根据类对象创建对应的实例对象
    Method methodObj = cls.getMethod(methodPro);//获取方法的对象
    //获取属性的对象,并设置属性值
    Field fieldObj = cls.getDeclaredField("name");
    fieldObj.setAccessible(true);//私有属性必须先爆破,才能设置值
    fieldObj.set(obj,nameProValue);
    //通过方法对象调用方法
    methodObj.invoke(obj);//hello jack
}



目录
相关文章
|
9天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
24 1
|
8天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
21 0
java基础(13)String类
|
9天前
|
Java
java基础(4)public class 和class的区别及注意事项
本文讲解了Java中`public class`与`class`的区别和注意事项。一个Java源文件中只能有一个`public class`,并且`public class`的类名必须与文件名相同。此外,可以有多个非`public`类。每个类都可以包含一个`main`方法,作为程序的入口点。文章还强调了编译Java文件生成`.class`文件的过程,以及如何使用`java`命令运行编译后的类。
15 3
java基础(4)public class 和class的区别及注意事项
|
2天前
|
Java API
Java的日期类都是怎么用的
【10月更文挑战第1天】本文介绍了 Java 中处理日期和时间的三个主要类:`java.util.Date`、`java.util.Calendar` 和 `java.time` 包下的新 API。`Date` 类用于表示精确到毫秒的瞬间,可通过时间戳创建或获取当前日期;`Calendar` 抽象类提供丰富的日期操作方法,如获取年月日及时区转换;`java.time` 包中的 `LocalDate`、`LocalTime`、`LocalDateTime` 和 `ZonedDateTime` 等类则提供了更为现代和灵活的日期时间处理方式,支持时区和复杂的时间计算。
26 14
|
6天前
|
安全 Java 编译器
java访问类字段
java访问类字段
|
8天前
|
Java
java的class类
java的class类
18 5
|
9天前
|
Java 数据处理
Java Scanner 类详解
`Scanner` 类是 Java 中 `java.util` 包提供的强大工具,用于从多种输入源(如键盘、文件、字符串)读取数据。本文详细介绍如何创建 `Scanner` 对象并使用其常用方法(如 `next()`, `nextInt()`, `nextLine()` 等)。通过示例代码展示如何从标准输入、字符串及文件中读取数据,并进行输入验证。使用时需注意关闭 `Scanner` 以释放资源,并确保输入类型匹配,避免异常。掌握 `Scanner` 可显著提升程序的数据处理能力。
|
9天前
|
存储 安全 Java
扫盲java基础-反射(一)
扫盲java基础-反射(一)
|
9天前
|
Java
扫盲java基础-反射(二)
扫盲java基础-反射(二)
|
2月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
47 7
下一篇
无影云桌面