https://www.bilibili.com/video/BV1ke4y1w7yn
什么是反射 ?
反射允许对字段(成员变量),成员方法和构造方法的信息进程编程访问。
获取类对象字节码文件的三种方式
Class.forName(“全类名”);
类名.class;
对象.getClass();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.qust;
import com.qust.reflect.Student;
public class Main { public static void main(String[] args) {
Class clazz1 = null; try { clazz1 = Class.forName("com.qust.reflect.Student"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
Class clazz2 = Student.class;
Class clazz3 = (new Student()).getClass();
System.out.println(clazz1);
System.out.println(clazz2);
System.out.println(clazz3);
} }
|
点击类名,点击 copy - cpoy as Reference,即可复制全类名(包名 + 类名)
利用反射获取成员变量信息
Class 中用于获取成员变量的方法
Field[] getFields()
: 返回所有公共成员变量对象的数组
Field[] getDeclaredFields()
: 返回所有成员变量对象的数组
Field getField()
: 返回单个公共成员变量对象
Field getDeclaredField()
: 返回单个成员变量对象
Field 类中用于创建对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package com.qust;
import com.qust.reflect_.Student;
import java.lang.reflect.Field;
public class Main { public static void main(String[] args) { Class clazz; try { clazz = Class.forName("com.qust.reflect_.Student"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
Field[] fields = clazz.getFields(); System.out.println("All public variable:"); for(Field f : fields) { System.out.println(f.getName()); } System.out.println();
fields = clazz.getDeclaredFields(); System.out.println("All variable:"); for(Field f : fields) { System.out.println(f.getName()); } System.out.println();
Field gender = null; try { gender = clazz.getField("gender"); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } System.out.println(gender); System.out.println();
Field name = null; try { name = clazz.getDeclaredField("name"); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } System.out.println(name); System.out.println();
System.out.println(name.getModifiers()); System.out.println(name.getName()); System.out.println(name.getType()); Student student = new Student(11, "wpc", "male"); name.setAccessible(true); Object value = null; try { value = name.get(student); } catch (IllegalAccessException e) { throw new RuntimeException(e); } System.out.println(value); try { name.set(student,"wpc_"); } catch (IllegalAccessException e) { throw new RuntimeException(e); } System.out.println(student); } }
|
利用反射获取成员方法
Class 类中获取成员方法的方法
Method[] getMethods() : 返回所有公共成员方法的数组,包括继承的
Method[] getDeclaredMethods()
Methods[] getMethod(String name, Class<?> … Parameters)
Methods[] getDeclaredMethod(String name, Class<?> … Parameters)
Method 类中用于创建对象的方法
- Object invoke(Object object, Object .. args) : 运行方法
参数一 :用 obj 对象调用该方法
参数二 :调用方法的传递的参数(没有就不写)
返回值 :方法的返回值(没有就不写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package com.qust;
import com.qust.reflect__.Student;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
public class Test { public static void main(String[] args) { Class clazz; try { clazz = Class.forName("com.qust.reflect__.Student"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
Method[] methods = clazz.getDeclaredMethods(); for(Method method : methods) { System.out.println(method.getName()); }
Method m = null; try { m = clazz.getMethod("eat", String.class); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } System.out.println(m);
int modifiers = m.getModifiers(); String name = m.getName(); m.getParameters(); m.getParameterCount(); m.getParameterTypes();
Class[] exps = m.getExceptionTypes();
try { String res = (String) m.invoke(new Student(), "shit"); System.out.println(res); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); }
Class<?> returnType = m.getReturnType(); System.out.println(returnType); } }
|
反射的作用
练习一 保存信息
对于任意一个对象,都可以把对象的所有字段名和值,保存到文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.qust.practice1;
import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field;
public class MyReflectDemo { public static void main(String[] args) throws IOException, IllegalAccessException { Student s = new Student("wpc", 21, "male", "learn", 180.5); Teacher t = new Teacher("teacher1", -100); System.out.println(System.getProperty("user.dir")); saveObjects(s); }
public static void saveObjects(Object obj) throws IOException, IllegalAccessException { Class clazz = obj.getClass();
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\95432\\Desktop\\Java-Reflect\\demo-reflect\\src\\main\\java\\com\\qust\\practice1\\data.txt"));
Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String name = field.getName(); Object value = field.get(obj); System.out.println(name + "=" + value); bw.write(name + "=" + value); bw.write("\n"); } bw.close(); } }
|
不知道为什么相对路径写入信息写不进去,也没提示找不到文件报错
练习二
跟配置文件结合,动态创建对象,并调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.qust.practice2;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Properties;
public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Properties prop = new Properties(); prop.load(new FileInputStream("C:\\Users\\95432\\Desktop\\Java-Reflect\\demo-reflect\\src\\main\\resources\\test .properties")); System.out.println(prop);
String className = (String) prop.get("classname"); String methodName = (String) prop.get("method");
System.out.println(className); System.out.println(methodName);
Class clazz = Class.forName(className); Constructor con = clazz.getDeclaredConstructor(); Object o = con.newInstance(); System.out.println(o);
clazz.getDeclaredMethod(methodName).invoke(o); } }
|
1 2
| classname=com.qust.practice2.Student method=learn
|
如果之后要运行别的类的方法,修改配置文件即可,例如修改为
className
classname=com.qust.practice2.Teacher
method=teach