反射的概念
Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种 动态的获取信息 以及 动态调用对象的方法 的功能称为 java 的反射机制。
反射机制很重要的一点就是“运行时”,其使得我们可以在程序运行时加载、探索以及使用编译期间完全未知的 .class 文件。
换句话说,Java 程序可以加载一个运行时才得知名称的 .class 文件,然后获悉其完整构造,并生成其对象实体、或对其 fields(变量)设值、或调用其 methods(方法
反射的好处: 通过反射技术可以获取到字节码文件对象,使用这个字节码文件对象就可以获取到一个类的所有信息,包括私有【构造方法对象,成员变量对象,成员方法对象,访问权限修饰符对象...】。
之前的做法:
Student s = new Student();
学习反射之后的做法: 可以不需要显示地出现学生类就能够创建学生类的对象,并且可以动态创建对象,动态赋值,动态调用方法
反射能够获取的相关对象
- Class 类对象
- Constructor 构造方法对象
- Method 成员方法对象
- Field 成员变量对象
- Modifier 访问权限修饰符对象
- Array 数组对象
创建反射字节码文件对象的三种方式
1.Class clazz = Class.forName("com.ashin.bean.Book");
该方法要注意的是会抛出一个ClassNotFoundException因为输入的字符串代表的类可能不存在。推荐这种方法
2.使用对象的getClass()来反向获取
Book book = new Book();
Class clazz = book.getClass();
必须得先生成对象
3.类字面常量
Class clazz = Book.class;
必须导入该类所在的包
通过反射获取构造方法对象
- Constructor<?>[] getConstructors() 获取到所有公有修饰的构造方法对象数组
- Constructor<?>[] getDeclaredConstructors() 获取所有构造方法对象数组,包括私有
- Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个公有修饰构造方法对象
- Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取所有单个修饰的构造方法对象,包括私有
例子
1 public class ReflectDemo01 {
2 public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException, IOException {
3 Student s1 = new Student("张三", 18, "北京西路", 1.80);
4 Student s2 = new Student("张三", 18, "北京西路", 1.80);
5 Class<? extends Student> c1 = s1.getClass();
6 Class<? extends Student> c2 = s2.getClass();
7
8 System.out.println(s1 == s2);
9 System.out.println(c1 == c2);
10
11 // Class<Integer> c3 = int.class;
12 Class<Student> c3 = Student.class;
13 System.out.println(c1 == c3);
14
15 Properties properties = new Properties();
16 properties.load(new FileReader("config/classinfo.properties"));
17 String classPath = properties.getProperty("className");
18 Class<?> c4 = Class.forName(classPath);
19 System.out.println(c1 == c4);
20
21 }
22 }
通过反射获取成员变量对象
- Field[] getFields() 获取所有公有的成员变量对象,包括父类的公有成员
- Field[] getDeclaredFields() 获取所有本类的成员,包括私有
- Field getDeclaredField(String name) 获取公有的成员属性,包括父类
- Field getField(String name) 获取所有本类属性,包括私有
1 public class ReflectDemo01 {
2 public static void main(String[] args) throws Exception {
3 Class<?> c = Class.forName("com.sxt.reflectdemo03.Student");
4 // 通过字节码文件对象获取成员变量对象
5 Field[] fields = c.getFields();
6 for (Field field : fields) {
7 System.out.println(field);
8 }
9
10 System.out.println("===============");
11 Field[] declaredFields = c.getDeclaredFields();
12 for (Field field : declaredFields) {
13 System.out.println(field);
14 }
15
16 System.out.println("===============");
17 Field nameField = c.getField("name");
18 System.out.println(nameField);
19
20 // Field heightField = c.getField("height");
21 // System.out.println(heightField);
22
23 Field heightField = c.getDeclaredField("height");
24 System.out.println(heightField);
25 }
26 }
通过反射获取成员方法对象,并且调用
原来方式:
Student s = new Student();
s.method();
- Method[] getMethods() 获取所有公有修饰的成员方法对象,包括父类公有方法
- Method[] getDeclaredMethods() 获取本类所有成员方法对象,包括私有方法
- Method getMethod(String name, Class<?>... parameterTypes)
- Method getDeclaredMethod(String name, Class<?>... parameterTypes)
1 public class ReflectDemo01 {
2 public static void main(String[] args) throws Exception {
3 Class<?> c = Class.forName("com.sxt.reflectdemo04.Student");
4 Object instance = c.getConstructor().newInstance();
5
6 // 通过字节码文件对象获取成员方法对象
7 Method[] methods = c.getMethods();
8 for (Method method : methods) {
9 System.out.println(method);
10 }
11
12 System.out.println("=================");
13 Method[] declaredMethods = c.getDeclaredMethods();
14 for (Method method : declaredMethods) {
15 System.out.println(method);
16 }
17
18 System.out.println("==================");
19 // 获取method方法
20 // Method getMethod(String name, Class<?>... parameterTypes)
21 Method method = c.getMethod("method");
22 System.out.println(method);
23
24 Object invoke = method.invoke(instance);
25 System.out.println(invoke);
26 System.out.println("==================");
27 // 获取setName方法并且赋值
28 Method setNameMethod = c.getMethod("setName", String.class);
29 setNameMethod.invoke(instance, "隔壁老周");
30
31 // 获取getName方法
32 Method getNameMethod = c.getMethod("getName");
33 Object result = getNameMethod.invoke(instance);
34 System.out.println(result);
35
36 // 获取add方法并且调用
37 Method addMethod = c.getMethod("add", int.class, int.class);
38 Object result3 = addMethod.invoke(instance, 10, 20);
39 System.out.println(result3);
40
41 // 获取私有方法并且调用
42 Method showMethod = c.getDeclaredMethod("show");
43 showMethod.setAccessible(true);
44 showMethod.invoke(instance);
45 }
46 }
通过反射获取数组Array对象并且赋值
1 public class ReflectDemo01 {
2 public static void main(String[] args) throws Exception {
3 Class<?> c = Class.forName("com.sxt.reflectdemo05.Demo");
4
5 Object instance = c.getConstructor().newInstance();
6
7 Field arrField = c.getDeclaredField("arr");
8
9 Object arr = arrField.get(instance);
10
11 // if (arr instanceof int[]) {
12 // int[] array = (int[]) arr;
13 // System.out.println(Arrays.toString(array));
14 // }
15 // int i = Array.getInt(arr, 0);
16 // System.out.println(i);
17 // Object obj = Array.get(arr, 0);
18 // System.out.println(obj);
19 // System.out.println(Array.get(arr, 1));
20 // System.out.println(Array.get(arr, 2));
21 //// System.out.println(Array.get(arr, 3));
22 // int length = Array.getLength(arr);
23 // System.out.println(length);
24
25 for (int i = 0; i < Array.getLength(arr); i++) {
26 System.out.println(Array.get(arr, i));
27 }
28
29 Array.set(arr, 2, 100);
30 System.out.println(Array.get(arr, 2));
31
32 // 通过反射创建数组
33 Object arrObj = Array.newInstance(String.class, 5);
34 for (int i = 0; i < Array.getLength(arrObj); i++) {
35 System.out.println(Array.get(arrObj, i));
36 }
37
38 Object arrobj2 = Array.newInstance(int.class, 2, 3);
39 // Object oneDimensson1 = Array.newInstance(int.class, 1);
40 // Object oneDimensson2 = Array.newInstance(int.class, 2);
41 //
42 // Array.set(arrobj2, 0, oneDimensson1);
43 // Array.set(arrobj2, 1, oneDimensson2);
44
45 if (arrobj2 instanceof int[][]) {
46 int[][] array = (int[][]) arrobj2;
47 System.out.println(array);
48 }
49 }
50 }
51
52 class Demo {
53
54 int[] arr = new int[3];
55
56 public Demo() {
57 arr[0] = 10;
58 arr[1] = 20;
59 }
}