反射
据我们所知,Java是一种静态语言。但是Java却可以通过Reflection(反射)
实现动态语言的特性,反射机制允许在执行期间借助Reflection API
取得任何类的内部信息,并且能直接操作任意对象的内部属性及方法。
反射对象相当于是一面镜子,通过镜子,"反射"得到对象的信息:某个类的属性、方法、构造器、实现的接口。
获得反射对象
通过对象获得
1
| Class c1 = person.getClass();
|
通过forname
获得
1
| Class c2 = Class.forName("cn.icewindy.test.Person");
|
通过类名.class获得
1
| Class c3 = Person.class;
|
验证一下:
1
| System.out.printf("c1:%s,c2:%s,c3:%s\n", c1.hashCode(), c2.hashCode(), c3.hashCode());
|
基本内置类型的包装类都有一个TYPE
属性
1
| Class c4 = Integer.TYPE;
|
获得父类类型
1 2 3
| Class c4 = student.getClass(); Class c5 = c4.getSuperclass(); System.out.printf("c5:%s\n", c5.hashCode());
|
拥有Class对象的类型
class 各种类、interface 接口、[] 数组、enum 枚举、annotation 注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Class c1 = Object.class; Class c2 = Comparable.class; Class c3 = String[].class; Class c4 = int[][].class; Class c5 = Override.class; Class c6 = ElementType.class; Class c7 = Integer.class; Class c8 = void.class; Class c9 = Class.class;
System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9);
|
类加载过程分析
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
| public class Test { public static void main(String[] args) { A a = new A(); System.out.println(a.m);
} }
class A{ static { System.out.println("A静态代码块初始化"); m = 300; }
static int m = 100;
public A(){ System.out.println("A构造函数初始化"); } }
|
out:
类的初始化发生
类的主动引用(会发生初始化)
- JVM启动,初始化main方法所在的类
- new一个类的对象
- 调用类的静态成员(除了常量final)和静态方法
- 使用
java.lang.reflect
包的方法对类进行反射调用
- 当初始化一个类,如果父类没有被初始化,则先初始化父类
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
| public class Test { static { System.out.println("Main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { Son son = new Son();
Class.forName("cn.icewindy.test.Son");
} } class Father{ static int a = 1; static { System.out.println("父类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); } static final int b = 2; }
|
类的被动引用(不会发生初始化)
- 当访问一个静态域,只有真正申明这个域的类才会被初始化。如:通过子类引用父类的静态变量,不会导致子类初始化
1 2 3 4 5 6 7 8
| System.out.println(Father.a); System.out.println(Son.a);
|
- 通过数组定义类的引用,不会发生此类初始化
1
| Son[] arraySon = new Son[5];
|
- 引用常量不会触发类的初始化
1 2 3 4 5
| System.out.println(Son.b);
|
获取类的结构
获取类的名称
-
getName()
可以获取包名+类名;
-
getSimpleName()
可以获取类名。
获取类的属性
Field getField(name)
根据name
获取某个public
的属性(包括父类);
Field getDeclaredField(name)
根据name
获取某个属性(不包括父类);
Field[] getFields()
获取所有public
的属性(包括父类);
Field[] getDeclaredFields()
获取所有属性(不包括父类)。
获得属性的值
Field.get(Object)
根据Object
实例获取其对应属性的值。
获取类的方法
Method getMethod(name, Class...)
获取某个public
的方法(包括父类)Classs
代表参数类型;
Method getDeclaredMethod(name, Class...)
:获取某个方法(不包括父类)Classs
代表参数类型;
Method[] getMethods()
获取所有public
的方法(包括父类);
Method[] getDeclaredMethods()
获取所有方法(不包括父类)。
获取类的构造器
getConstructor(Class...)
:获取某个public
的构造器;
getDeclaredConstructor(Class...)
:获取某个构造器;
getConstructors()
:获取public
的构造器;
getDeclaredConstructors()
:获取所有构造器。
例子1:
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
| import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class Demo { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException { Class s = Class.forName("cn.icewindy.test.Student"); System.out.println(s.getName()); System.out.println(s.getSimpleName()); Field[] fields = s.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } Field[] fields2 = s.getFields(); for (Field field : fields2) { System.out.println(field); } Field field = s.getField("name"); Object value = field.get(new Student()); System.out.println(value); Method[] methods = s.getMethods(); for (Method method : methods) { System.out.println(method); } Method[] methods2 = s.getDeclaredMethods(); for(Method method : methods2){ System.out.println(method); } Method method = s.getMethod("say", String.class); System.out.println(method); Constructor[] constructors = s.getConstructors(); for(Constructor constructor : constructors){ System.out.println(constructor); } } } class Person{ public String name = "icewindy"; public int age = 18; public void sayHello(){ System.out.println("hello"); } } class Student extends Person{ public Student(){ System.out.println("I am a Student"); } private int ID = 114514; public void study(){ System.out.println("Student is studying"); } private void talk(){} public void say(String str){ System.out.println("Student is saying: "+str); } }
|
调用方法
调用构造器
例子2: