反射API
Java.lang.Reflect库
① Class类与Java.lang.Reflect类库一起对反射的概念进行支持。
② java.lang包下:
a) Class<T>:表示对一个正在运行的Java应用程序中的类和接口,是Reflection的起源。
③ java.lang.reflect包下:
a) Field类:代表类的成员变量(成员变量也称类的属性)。
b) Method类:代表类的方法。
c) Constructor类:代表类的构造方法。
d) Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
通过反射实例化对象
① 常情况下我们通过new Object来生成一个类的实例,但有时我们没法直接new,只能通过反射动态生成。
② 实例化无参构造函数的对象,两种方式:
a) Class.newlnstance();
b) Class.getConstructor(new Class[]{}).newInstance(new Object[]{})
③ 实化带参构造函数的对象
a) clazz.getConstructor(Class<?>… parameterTypes).newInstance(Object… initargs)
通过反射获取并调用方法
① 得当前类以及超类的public Method(共有方法)
a) Method[] arrMethod=classType.getMethods();
② 得当前类申明的所有Method
a) Method[] arrMethod=classType.getDeclaredMethods();
③ 获得当前类以及超类指定的public Method
a) Method method=classType.getMethod(String name,Class<?>… parameterTypes);
④ 得当前类申明的指定的Method
a) Method method=classType. getDeclaredMethods (String name,Class<?>… parameterTypes);
⑤ 通过反射动态运行指定Method
a) Object obj=method.invoke(Object obj,Object… args);
通过反射获取并调用属性
① 得当前类以及超类的public Field
a)Field[] arrFields=classType.getField();
② 获得当前类申明的所有Field
a)Field[] arrFields=classType.getDeclaredFields();
③ 获得当前类以及超类指定的public Field
a) Field field=classType.getField(String name);
④ 获得当前类申明的指定的Field
a) Field field=classType.getDeclaredField(String name);
⑤ 通过反射动态设定Field的值
a) field.set(Object obj,Object value);
⑥ 通过反射动态获取Field的值
a) Object obj=field.get(Object obj);
----------------------------------------------------------------------------------------------------
代码
创建一个Employee类
1 class Employee {
2 private String name;
3 private int age;
4
5 public Employee() {
6 System.out.println("无参构造方法");
7 }
8
9 public String getName() {
10 return name;
11 }
12
13 public void setName(String name) {
14 this.name = name;
15 }
16
17 public int getAge() {
18 return age;
19 }
20
21 public void setAge(int age) {
22 this.age = age;
23 }
24
25 public Employee(String name, int age) {
26 super();
27 this.name = name;
28 this.age = age;
29 }
30
31 @Override
32 public String toString() {
33 return "Employee [name=" + name + ", age=" + age + "]";
34 }
35
36 private void work() {
37 System.out.println("working...");
38 }
39
40 }
在主方法中获取类的属性及方法:
1 // 获取Employee这个类所关联的class对象
2 Class<?> classType = Class.forName("com.iotek.reflection.Employee");
3 // 通过反射机制来构造一个Employee的实例对象(默认调用无参数的构造方法)
4 Employee employee = (Employee) classType.newInstance();
5 System.out.println(employee);
输出结果:
无参构造方法
Employee [name=null, age=0]
1 // 调用指定的构造方法来构造对象(无参构造方法)
2 Constructor<?> constructor = classType.getConstructor(new Class[] {});
3 Employee employee2 = (Employee)constructor.newInstance(new Object[] {});
4 System.out.println(employee2);
输出结果:
无参构造方法
Employee [name=null, age=0]
1 // 调用指定的构造方法来构造对象(带参构造方法)
2 Constructor<?> constructor2 = classType.getConstructor(new Class[] {String.class, int.class });
3 Employee employee3 = (Employee) constructor2.newInstance(new Object[] {"zhangsan", 20 });
4 System.out.println(employee3);
输出结果:
Employee [name=zhangsan, age=20]
1 // 获取Class对象所指定的所有方法,包括私有的
2 Method[] methods = classType.getDeclaredMethods();
3 for (Method method : methods) {
4 System.out.println(method.getName() + "--" + method.getModifiers()
5 + "--" + method.getReturnType());
6 }
输出结果:
toString--1--class java.lang.String
getName--1--class java.lang.String
setName--1--void
work--2--void
getAge--1--int
setAge--1—void
1 // 获取Class对象所指定的方法,包括私有的
2 Method method2 = classType
3 .getDeclaredMethod("toString", new Class[] {});
4 System.out.println(method2);
5 // 方法的调用
6 String desc = (String) method2.invoke(employee3, new Object[] {});
7 System.out.println(desc);
输出结果:
public java.lang.String com.iotek.reflection.Employee.toString()
Employee [name=zhangsan, age=20]
1 // 调用私有方法
2 Method method3 = classType.getDeclaredMethod("work", new Class[] {});
3 System.out.println(method3.getName());
4 method3.setAccessible(true);// 设置私有方法可以访问
5 // 方法的调用
6 method3.invoke(employee3, new Object[] {});
输出结果:
work
working...
1 // 获取Class对象所指定的属性,包括私有的
2 Field field = classType.getDeclaredField("name");
3 field.setAccessible(true);
4 field.set(employee3, "李四");
5 System.out.println(field.get(employee3));
输出结果:
李四
使用反射来创建一维数组:
1 // 创建一个一维数组(String)
2 Class<?> classType = Class.forName("java.lang.String");
3 Object array = Array.newInstance(classType, 5);
4 Array.set(array, 3, "abc");
5 System.out.println(Array.get(array, 3));
输出结果:
abc
使用反射来创建二维数组:
1 // 创建一个二维数组(3行3列)
2 int[] dimens = { 3, 3 };
3 Object array2 = Array.newInstance(int.class, dimens);
4 Object arrayObj = Array.get(array2, 2);// 获取第三行(就是一个一维数组)
5 Array.setInt(arrayObj, 2, 10);// 给指定数组位置的元素赋值
6 int [][] arr = (int [][]) array2;
7 System.out.println(arr[2][2]);
输出结果:
10
反射总结:
① 只要用到反射,先获得Class对象。
② 没有方法能获得当前类的超类的private方法和属性,你必须通过getSuperclass()找到超类以后再去尝试获得。
③ 通常情况下即使是当前类,private属性或方法也是不能访问的,你需要设置压制权限setAccessible(true)来取得private的访问权。但是,这已经破坏了面向对象的规则,所以除非万不得已,请尽量少用。