核心内容摘要
Z-Image-GGUF多场景:小红书封面、公众号头图、B站视频缩略图定制生成
反射概述
1 什么是反射反射Reflection是 Java 提供的强大特性允许程序在运行时动态地获取、访问类的所有信息包括类名、属性、方法、构造器、注解等并能动态操作这些信息突破编译期的访问限制。
2 反射的作用获取类信息运行时获取对象所属类的名称、包名、父类、实现的接口等动态创建对象无需new关键字通过类名字符串构造任意类的对象访问成员变量获取类的所有变量包括私有、final 变量并读写其值调用方法获取类的所有方法包括私有方法并动态调用解析注解运行时读取类 / 方法 / 属性上的注解是框架实现注解驱动的核心。
Class 类反射的根源
1 Class 类概述JVM 加载完类后会在堆内存的方法区中生成一个Class类型的对象 —— 这个对象是该类的 “说明书”包含了类的所有信息类名、父类、接口、属性、方法、构造器等。
核心特点每个类在 JVM 中只有一份字节码对应唯一的Class对象Class对象是反射的入口所有反射操作都基于Class对象展开无论是自定义的Person类还是 JDK 内置的String/ArrayList加载后都会生成对应的Class对象。
2 获取 Class 对象的三种方式附案例获取Class对象有三种核心方式以下以Student类为例演示第一步定义 Student 测试类java运行public class Student { private String name; private int age; private String address; // 构造方法私有、默认、公共多参 public Student() {} private Student(String name) {this.name name;} Student(String name, int age) {this.name name; this.age age;} public Student(String name, int age, String address) { this.name name; this.age age; this.address address; } // 成员方法私有、公共无参/有参/有返回值 private void function() {System.out.println(执行function());} public void method1() {System.out.println(执行method1());} public void method2(String s) {System.out.println(执行method2(): s);} public String method3(String s, int i) {return 执行method3():s , i;} Override public String toString() { return Student{ name name \ , age age , address address \ }; } }第二步获取 Class 对象的三种方式java运行public class ClassTest { public static void main(String[] args) throws ClassNotFoundException { // 方式1类.class编译期确定最安全 System.out.println(---------方式1类.class---------); ClassStudent c1 Student.class; System.out.println(c
; // class com.hg.java.Student ClassStudent c2 Student.class; System.out.println(c1 c
; // true同一Class对象 // 方式2对象.getClass()运行时获取适用于已有对象的场景 System.out.println(---方式2对象.getClass()---); Student s new Student(); Class? extends Student c3 s.getClass(); System.out.println(c1 c
; // true // 方式3Class.forName(全类名)动态加载最灵活适用于配置文件场景 System.out.println(----方式3Class.forName(全类名)----); Class? c4 Class.forName(com.hg.java.Student); System.out.println(c1 c
; // true } }
Constructor操作类的构造器
1 Constructor 类概述java.lang.reflect.Constructor是反射体系中描述类的构造器的类类的每个构造器无参 / 有参、公有 / 私有都对应一个Constructor对象通过Constructor对象可在运行时创建类的实例甚至调用私有构造器。
2 获取 Constructor 对象的方法附案例方法说明Constructor?[] getConstructors()返回所有公共构造方法的数组Constructor?[] getDeclaredConstructors()返回所有构造方法的数组含私有Constructor getConstructor(Class?... parameterTypes)返回单个公共构造方法指定参数类型Constructor getDeclaredConstructor(Class?...parameterTypes)返回单个构造方法含私有指定参数类型案例获取 Student 类的构造器java运行public class ConstructorTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Class? c Class.forName(com.hg.java
Student); //
获取所有构造器含私有 System.out.println(---返回所有构造方法的数组----); Constructor?[] cons c.getDeclaredConstructors(); for (Constructor con : cons) { System.out.println(con); } //
获取单个公共构造器 System.out.println(-----返回单个构造方法----); Constructor? con c.getConstructor(); // 无参构造 System.out.println(con); con c.getConstructor(String.class, int.class, String.class); // 三参构造 System.out.println(con); } }
3 Constructor 常用方法附案例核心方法T newInstance(Object...initargs)—— 根据指定构造器创建对象。
java运行public class ConstructorTest { public static void main(String[] args) throws Exception { Class? c Class.forName(com.hg.java
Student); //
通过无参构造创建对象 System.out.println(------通过反射获取公共构造方法并创建对象--------); Constructor? con c.getConstructor(); Student s1 (Student) con.newInstance(); System.out.println(s
; // Student{namenull, age0, addressnull} //
通过三参构造创建对象 con c.getConstructor(String.class, int.class, String.class); Object obj con.newInstance(林青霞, 30, 西安); System.out.println(obj); // Student{name林青霞, age30, address西安} } }
Field操作类的成员变量
1 Field 类概述java.lang.reflect.Field是反射体系中描述类的成员变量的类每个成员变量公有 / 私有、静态 / 实例、final都对应一个Field对象通过Field对象可在运行时读写变量值突破访问权限限制。
2 获取 Field 对象的方法附案例方法说明Field[] getFields()返回所有公共成员变量的数组Field[] getDeclaredFields()返回所有成员变量的数组含私有Field getField(String name)返回单个公共成员变量指定变量名Field getDeclaredField(String name)返回单个成员变量含私有指定变量名案例获取 Student 类的成员变量java运行public class FieldTest { public static void main(String[] args) throws Exception { Class? c Class.forName(com.hg.java
Student); //
获取所有公共成员变量 System.out.println(---------返回所有公共成员变量的数组----------); Field[] fields c.getFields(); for (Field field : fields) { System.out.println(field); } //
获取所有成员变量含私有 System.out.println(---------返回所有成员变量的数组----------); fields c.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } //
获取单个公共成员变量 System.out.println(---------返回单个公共成员变量----------); Field addressField c.getField(address); System.out.println(addressField); //
获取单个私有成员变量 System.out.println(---------返回单个私有成员变量----------); Field nameField c.getDeclaredField(name); System.out.println(nameField); } }
3 Field 常用方法附案例核心方法void set(Object obj,Object value)—— 给指定对象的成员变量赋值。
java运行public class FieldTest { public static void main(String[] args) throws Exception{ Class? c Class.forName(com.hg.java
Student); // 先通过构造器创建对象 Constructor? con c.getConstructor(); Object obj con.newInstance(); //
给公共变量address赋值 Field addressField c.getField(address); addressField.set(obj, 西安); System.out.println(obj); // Student{namenull, age0, address西安} //
给私有变量age赋值默认禁止访问需先解除限制 Field ageField c.getDeclaredField(age); ageField.setAccessible(true); // 解除访问权限检查 ageField.set(obj,
; System.out.println(obj); // Student{namenull, age30, address西安} } }
Method操作类的成员方法
1 Method 类概述java.lang.reflect.Method是反射体系中描述类的成员方法的类每个方法公有 / 私有、静态 / 实例、有参 / 无参都对应一个Method对象通过Method对象可在运行时调用方法包括私有方法。
2 获取 Method 对象的方法附案例方法说明Method[] getMethods()返回所有公共成员方法的数组含父类继承的Method[] getDeclaredMethods()返回所有成员方法的数组仅本类含私有Method getMethod(String name, Class?... parameterTypes)返回单个公共方法指定方法名 参数类型Method getDeclaredMethod(String name, Class?... parameterTypes)返回单个方法含私有指定方法名 参数类型案例获取 Student 类的成员方法java运行public class MethodTest { public static void main(String[] args) throws Exception { Class? c Class.forName(com.hg.java
Student); //
获取所有公共方法含toString、equals等父类方法 System.out.println(-----------返回所有公共成员方法的数组--------); Method[] methods c.getMethods(); for (Method method : methods) { System.out.println(method); } //
获取所有本类方法含私有 System.out.println(-----------返回所有成员方法的数组--------); methods c.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } //
获取单个公共方法 System.out.println(-----------返回单个公共成员方法--------); Method method c.getMethod(method
; // 无参 System.out.println(method); Method method2 c.getMethod(method2, String.class); // 单参 System.out.println(method
; Method method3 c.getMethod(method3, String.class, int.class); // 双参 System.out.println(method
; //
获取私有方法 System.out.println(-----------返回单个非公共成员方法--------); Method method4 c.getDeclaredMethod(function); System.out.println(method
; } }
3 Method 常用方法附案例核心方法Object invoke(Object obj,Object... args)—— 调用指定对象的方法参数为args返回值为方法执行结果。
java运行public class MethodTest { public static void main(String[] args) throws Exception { Class? c Class.forName(com.hg.java
Student); // 创建对象 Constructor? con c.getConstructor(); Object obj con.newInstance(); //
调用无参公共方法 Method method c.getMethod(method
; method.invoke(obj); // 执行method1() //
调用单参公共方法 Method method2 c.getMethod(method2, String.class); method
invoke(obj, 林青霞); // 执行method2():林青霞 //
调用有返回值的公共方法 Method method3 c.getMethod(method3, String.class, int.class); Object o method
invoke(obj, 林青霞,
; System.out.println(o); // 执行method3():林青霞,30 //
调用私有方法需解除访问限制 Method method4 c.getDeclaredMethod(function); method
setAccessible(true); method
invoke(obj); // 执行function() } }
Annotation操作类的注解
1 Annotation 类概述java.lang.annotation.Annotation是反射体系中描述注解的类每个加在类 / 方法 / 属性上的注解都对应一个Annotation对象反射可运行时读取注解的属性值判断元素是否被注解标记框架核心用法注解必须标注Retention(RetentionPolicy.RUNTIME)否则反射无法读取。
2 获取 Annotation 对象的方法附案例方法说明Annotation[] getAnnotations()返回元素上的所有注解含继承的Annotation[] getDeclaredAnnotations()返回元素上的所有注解仅本元素Annotation getAnnotation(Class? annoClass)返回指定类型的注解含继承的Annotation getDeclaredAnnotation(Class? annoClass)返回指定类型的注解仅本元素isAnnotationPresent(ClassA annoClass)判断元素是否被指定注解标记案例解析类 / 属性 / 方法上的注解java运行import java.lang.annotation.*; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.annotation.Annotation; public class AnnotationTest { public static void main(String[] args) throws Exception { Class? clazz Class.forName(com.hg.java
SampleClass); //
解析类上的注解 System.out.println(----------解析类上的注解---------); if (clazz.isAnnotationPresent(CustomAnnotation.class)) { CustomAnnotation customAnnotation clazz.getAnnotation(CustomAnnotation.class); System.out.println(类注解-name: customAnnotation.name()); System.out.println(类注解-value: customAnnotation.value()); } //
解析属性上的注解 System.out.println(----------解析属性上的注解---------); Field field clazz.getDeclaredField(sampleField); if (field.isAnnotationPresent(CustomAnnotation.class)) { CustomAnnotation customAnnotation field.getAnnotation(CustomAnnotation.class); System.out.println(属性注解-name: customAnnotation.name()); System.out.println(属性注解-value: customAnnotation.value()); } //
解析方法上的注解 System.out.println(----------解析方法上的注解---------); Method method clazz.getMethod(getSampleField); if (method.isAnnotationPresent(CustomAnnotation.class)) { CustomAnnotation customAnnotation method.getAnnotation(CustomAnnotation.class); System.out.println(方法注解-name: customAnnotation.name()); System.out.println(方法注解-value: customAnnotation.value()); } } } // 自定义注解必须指定RUNTIME保留策略 Retention(RetentionPolicy.RUNTIME) interface CustomAnnotation { String name() default 这是name; String value() default 这是value; } // 测试类 CustomAnnotation(nameSampleClass, value Sample Class Annotation) class SampleClass { CustomAnnotation(namesampleField, value Sample Field Annotation) private String sampleField; CustomAnnotation(namegetSampleMethod, value Sample Method Annotation) public String getSampleField() { return sampleField; } public void setSampleField(String sampleField) { this.sampleField sampleField; } }
实战作业3 道经典反射练习题作业 1通过反射越过泛型检查给 ArrayListInteger添加字符串要求反射突破泛型的编译期检查往ArrayListInteger中添加字符串数据。
java运行// 提示泛型仅在编译期生效运行时会被擦除反射可直接调用add方法 ArrayListInteger intList new ArrayList(); intList.add(
; // 请补充反射代码添加字符串Hello Reflection作业 2通过反射运行配置文件中指定类的指定方法要求使用Properties解析配置文件反射调用指定类的指定方法。
配置文件student.propertiespropertiesclassNamecom.java.exer.Student methodNamestudyStudent 类java运行public class Student { public void study() { System.out.println(好好学习天天向上); } }作业 3反射解析注解并动态调用方法要求判断StudentController类是否添加MyController注解若添加则将标注MyRequestMapping的方法存入HashMap控制台输入方法名调用对应的方法。
自定义注解java运行Retention(RetentionPolicy.RUNTIME) public interface MyController { String name() default 这是name; String value() default 这是value; } Retention(RetentionPolicy.RUNTIME) public interface MyRequestMapping { String name() default 这是name; String value() default 这是value; }StudentController 类java运行MyController public class StudentController { MyRequestMapping public void method1() { System.out.println(执行了method1()); } public void method2() { System.out.println(执行了method2()); } MyRequestMapping public void method3() { System.out.println(执行了method3()); } }
总结反射是 Java 中极具威力的特性核心是通过 JVM 中的类元数据突破编译期限制实现动态化编程。
掌握Class、Constructor、Field、Method、Annotation的使用是理解 Spring 等框架底层原理的关键。
建议结合本文案例动手实践再完成课后作业彻底掌握反射的核心用法。