C:\Users\ikeife\.jdks\corretto-21.0.3\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\IntelliJ IDEA 2023.3.7\lib\idea_rt.jar=52251:D:\IntelliJ IDEA 2023.3.7\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath "D:\IntelliJ IDEA 2023.3.7\lib\idea_rt.jar;D:\IntelliJ IDEA 2023.3.7\plugins\junit\lib\junit5-rt.jar;D:\IntelliJ IDEA 2023.3.7\plugins\junit\lib\junit-rt.jar;E:\work-testroot\study\java\javago\out\production\java go1;C:\Users\ikeife\.m2\repository\org\jetbrains\kotlin\kotlin-stdlib-jdk8\1.9.23\kotlin-stdlib-jdk8-1.9.23.jar;C:\Users\ikeife\.m2\repository\org\jetbrains\kotlin\kotlin-stdlib\1.9.23\kotlin-stdlib-1.9.23.jar;C:\Users\ikeife\.m2\repository\org\jetbrains\annotations\13.0\annotations-13.0.jar;C:\Users\ikeife\.m2\repository\org\jetbrains\kotlin\kotlin-stdlib-jdk7\1.9.23\kotlin-stdlib-jdk7-1.9.23.jar;C:\Users\ikeife\.m2\repository\junit\junit\4.13.1\junit-4.13.1.jar;C:\Users\ikeife\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 javago.StringUtilsTest
进程已结束,退出代码为 0
反射
加载类,并允许以编程的方式解剖类中的各种成分(成员变量。方法,构造器)
如何获取类的信息并操作他们
加载类,获取字节码:获取了class对象
获取类的构造器 Constructor对象
获取类的成员变量 Field对象
获取类的成员方法 Method对象
应用场景:
获取Class对象
Class c1 = 类名.class
调用Class提供方法:public static Class forName(String package);
Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();
Test1Class.java(三种方法都有了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
package javahight;
public class Test1Class{ public static void main(String[] arges){ Class c1 = Students.class; System.out.println(c1.getName());//运行可得javahight.Students是包名+类名 叫做全类名 System.out.println(c1.getSimpleName());//得到类名 Students Class c2 = Class.forName("javahight.Students"); System.out.println(c1==c2); Students s = new Students(); Class c3 = s.getClass(); } }
Students.java
1 2 3 4 5
package javahight; class Students{
}
获取类完成了
获取类的构造器
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
package javahight;
import java.lang.reflect.Constructor;
class Test1 { public static void main(String[] args) { testGetConstructor(); }
public static void testGetConstructor() { Class<?> c = Students.class;//获取类 Constructor<?>[] constructors = c.getConstructors(); // 获取类的全部构造器 for (Constructor<?> constructor : constructors) {//遍历所以 System.out.println(constructor.getName() + " has " + constructor.getParameterCount() + " parameters");//输出 } } }
这个方法只能拿pubilc的
1 2 3 4 5 6 7
publicstaticvoidtestGetConstructor() { Class<?> c = Students.class;//获取类 Constructor<?>[] constructors = c.getDeclaredConstructors(); // 获取类的全部构造器 for (Constructor<?> constructor : constructors) {//遍历所以 System.out.println(constructor.getName() + " has " + constructor.getParameterCount() + " parameters");//输出 } }
在 Students 类中添加 toString 方法,使其返回包含对象属性的字符串。这样可以确保在打印 Students 对象时,会显示对象的属性而不是默认的类名和内存地址。
1 2 3 4
@Override public String toString() { return"Students{name='" + name + "', age=" + age + "}"; }
获取类的成员变量
1 2 3 4 5 6 7 8 9
public static class Test { public void testGetFields() { Class<?> s = Students.class;//反射 Field[] fields = s.getDeclaredFields(); // 获取类的所有字段 for (Field field : fields) {//变量输出 System.out.println(field.getName() + " : " + field.getType()); } } }
return
1 2 3 4 5
name : class java.lang.String age : int a : int country : class java.lang.String
拿之前的方法就也能拿到单个的成员变量
1 2
Field fname = s.getDeclaredField("name"); System.out.println(fname.getName());
return:
1
name
接下来是为了成员变量赋值
1 2 3 4 5 6 7 8 9 10 11 12
try { Field fname = s.getDeclaredField("name"); System.out.println(fname.getName());
Students students = new Students(); fname.setAccessible(true); fname.set(students, "大"); // 设置students对象的name字段 System.out.println(students); // 打印students对象,查看修改后的name字段 } catch (Exception e) { e.printStackTrace(); } }
最后回显
1 2
name Students{name='大', age=0}
获取成员方法
1 2 3 4 5 6 7
public void testGetFields() { Class s = Students.class;//反射第一步 Method[] methods = s.getDeclaredMethods();//获取方法 for(Method method : methods){//遍历输出 System.out.println(method.getName() + "---" + method.getParameterCount() + "---" + method.getReturnType()); } }
Class s = Students.class; String setAge; Method method = s.getDeclaredMethod("getName"); System.out.println(method.getName() + "---" + method.getParameterCount() + "---" + method.getReturnType());
回显
1
getName---0---class java.lang.String
1 2 3 4 5 6 7 8 9 10 11 12
static class Test { public void testInvokeMethod() throws Exception { Class<?> s = Students.class; Method method = s.getDeclaredMethod("printStudentInfo");
Students students = new Students("Alice", 20); method.setAccessible(true); method.invoke(students);
System.out.println("aaa");//触发执行 } }
return
1 2
Name: Alice, Age: 20, Country: china aaa
反射的作用
适合做java的框架
简易框架的开发:
Test1Class.java
1 2 3 4 5 6 7 8 9 10 11 12 13
package javahight;
import org.junit.Test;
import java.io.ObjectStreamException;
public class Test1Class{ @Test public void save() throws Exception { Students s1 = new Students("zhou","18"); ObjectSaver.saveObject(s1); } }
public class testannotation { @Test public void parseClass(){ Class c = test.class; //判断类上是不是包含了注解 if(c.isAnnotationPresent(anntation.class)) { (anntation) c.getDeclaredAnnotations(anntation.class); System.out.println(); } } }