Java反射机制概述
- Reflection(反射)是被视为动态语言的关键,反射机智允许程序在执行期间通过 ReflectionAPI 取得任何类内部信息,并能直接操作任意对象的内部属性及方法
- 加载完类之后,在堆内部的方法区中就产生了一个Class类型的对象,一个类只有个一个Class对象,这个对象就包含了完整类的结构信息。我们通过这个对象看到类的内部结构。这个对象就像一个镜子,透过镜子看到类的内部结构,所以形象的称为“反射”
两种方式:
- 正常方式:引入需要的包类名称  ->  通过new实例化  ->  取得完整的实例
- 反射方式:实例化对象  ->  getClass 方法  ->  得到完整的包类名称
Java反射机制提供的功能
- 在运行时判断任意一个对象的所属类
- 在运行时判断任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
反射类的使用
| 12
 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
 
 | package com.songzx.reflection;
 import org.junit.Test;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 
 public class ReflectionTest {
 @Test
 
 
 
 
 
 
 
 public void test1(){
 
 Person p = new Person("张三", 15);
 p.show();
 System.out.println(p.toString());
 }
 
 @Test
 
 
 
 
 
 
 public void test2() throws Exception{
 
 Class<Person> perCls = Person.class;
 
 Constructor<Person> constructor = perCls.getConstructor(String.class, int.class);
 
 Person p = constructor.newInstance("张三", 15);
 
 System.out.println(p.toString());
 
 System.out.println("******通过反射调用对象指定的属性方法*********");
 
 Field age = perCls.getDeclaredField("age");
 
 age.set(p,20);
 System.out.println(p.toString());
 
 System.out.println("******通过反射调用方法*********");
 
 Method show = perCls.getDeclaredMethod("show");
 show.invoke(p);
 
 System.out.println("******通过反射调用类里面的私有方法*********");
 
 Constructor<Person> cons1 = perCls.getDeclaredConstructor(String.class);
 cons1.setAccessible(true);
 
 Person p1 = cons1.newInstance("Tome");
 System.out.println(p1.toString());
 
 
 System.out.println("******通过反射调用类里面的私有方法*********");
 
 Method getState = perCls.getDeclaredMethod("getState");
 getState.setAccessible(true);
 getState.invoke(p1);
 }
 }
 
 | 
类的加载过程
- 程序经过 java.exe 编译过后会生成一个或者多个字节码文件(.class) 结尾的
- 接着我们通过 java.exe 解释运行字节码文件,相当于把一个字节码文件编译到内存中,此过程称为类的加载过程。
- 加载到内存中的类称为运行时类,就作为一个 class 实例
- Class 对应着一个运行时类
- 加载到内存中的类会缓存一段时间,在这期间我们可以通过不同的方式来获取到运行时类
获取运行时类的多种方式
| 12
 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
 
 | package com.songzx.reflection;
 public class GetRunClassTest {
 
 
 
 
 
 
 public static void main(String[] args) throws Exception{
 
 Person p1 = new Person("张三",2);
 Class<? extends Person> clzz1 = p1.getClass();
 System.out.println(clzz1);
 
 
 Class<Person> clzz2 = Person.class;
 System.out.println(clzz2);
 
 
 Class<?> clzz3 = Class.forName("com.songzx.reflection.Person");
 System.out.println(clzz3);
 
 
 ClassLoader classLoader = GetRunClassTest.class.getClassLoader();
 Class<?> clzz4 = classLoader.loadClass("com.songzx.reflection.Person");
 System.out.println(clzz4);
 
 
 System.out.println(clzz1 == clzz2);
 System.out.println(clzz1 == clzz3);
 System.out.println(clzz1 == clzz4);
 
 
 }
 }
 
 | 
读取配置文件的两种方式
- FileInputStream读取文件获取
- getClassLoader获取
| 12
 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
 
 | package com.songzx.reflection;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
 
 public class ProprtoesTest {
 public static void main(String[] args) throws IOException {
 Properties pro = new Properties();
 
 
 
 
 
 
 ClassLoader classLoader = ProprtoesTest.class.getClassLoader();
 InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc.properties");
 pro.load(resourceAsStream);
 
 
 String user = pro.getProperty("user");
 String password = pro.getProperty("password");
 System.out.println(user);
 System.out.println(password);
 
 }
 }
 
 | 
创建运行时类的对象
在 javabin 中要求提供一个空参的构造器:
- 便于通过反射,创建运行时类的对象
- 便于子类继承父类时,默认调用 super(),需要保证父类有此构造器
- 调用 newInstance 方法,这个方法内部会调用 Person 类的空参构造器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | package com.songzx.reflection;
 public class NewInstanceTest {
 public static void main(String[] args) {
 
 Class<Person> personClass = Person.class;
 
 try {
 
 
 
 Person person = personClass.newInstance();
 System.out.println(person);
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 }
 }
 }
 
 | 
体会反射带来的动态性
| 12
 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
 
 | package com.songzx.reflection;
 import org.junit.Test;
 
 import java.util.Random;
 
 
 
 
 
 
 
 public class NewInstanceTest2 {
 @Test
 public void randomClass(){
 
 int num = new Random().nextInt(3);
 String classPath = "";
 switch (num){
 case 0:
 classPath = "java.util.Random";
 break;
 case 1:
 classPath = "java.util.Date";
 break;
 case 2:
 classPath = "com.songzx.reflection.Person";
 break;
 }
 try {
 
 Object instances = getInstances(classPath);
 System.out.println(instances);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 
 
 public Object getInstances(String classPath) throws Exception{
 Class<?> aClass = Class.forName(classPath);
 return aClass.newInstance();
 }
 
 }
 
 | 
获取运行时类的属性
- personClass.getFields()获取运行时类中和所有父类中声明为 public 权限的属性
- personClass.getDeclaredFields()只获取运行时类中的所有声明过的属性- 
- field.getModifiers()获取权限名称,返回的是一个int类型- 
- Modifier.toString(modifiers)将上面返回的int转为string类型的权限名称
 
- field.getType()获取数据类型
- field.getName()获取属性名称
 
| 12
 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
 
 | package com.songzx.person;
 import org.junit.Test;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 
 public class PersonInstances {
 @Test
 public void test1(){
 
 Class<Person> personClass = Person.class;
 
 Field[] fields = personClass.getFields();
 for (Field field : fields) {
 
 
 
 
 System.out.println(field);
 }
 
 System.out.println("****************");
 
 
 Field[] declaredFields = personClass.getDeclaredFields();
 for (Field field : declaredFields) {
 
 
 
 
 
 System.out.println(field);
 }
 }
 
 
 
 
 
 
 @Test
 public void test2(){
 Class<Person> personClass = Person.class;
 Field[] declaredFields = personClass.getDeclaredFields();
 for (Field field : declaredFields) {
 
 int modifiers = field.getModifiers();
 
 System.out.print(modifiers + "\t");
 
 String modifName = Modifier.toString(modifiers);
 System.out.print(modifName + "\t");
 
 
 Class<?> type = field.getType();
 System.out.print(type + "\t");
 
 
 String name = field.getName();
 System.out.println(name);
 }
 }
 }
 
 | 
获取运行时类的方法
- personClass.getMethods()获取当前运行时类以及所有父类的声明为 public 权限的方法
- personClass.getDeclaredMethods() 获取当前运行时类声明的所有方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | package com.songzx.person;
 import java.lang.reflect.Method;
 
 
 
 
 
 public class PersonMetheds {
 public static void main(String[] args) {
 Class<Person> personClass = Person.class;
 
 Method[] methods = personClass.getMethods();
 for (Method method : methods) {
 System.out.println(method);
 }
 
 System.out.println("************");
 
 
 Method[] declaredMethods = personClass.getDeclaredMethods();
 for (Method declaredMethod : declaredMethods) {
 System.out.println(declaredMethod);
 }
 }
 }
 
 | 
获取运行时类的方法内部结构
- getAnnotations()获取注解信息
- getModifiers()获取方法的权限修饰符
- getReturnType()获取方法返回值类型
- getName()获取方法名称
- getParameterTypes()获取方法形参列表
- getExceptionTypes()获取异常数组
| 12
 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
 77
 
 | package com.songzx.person;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 
 
 
 
 
 
 
 
 
 
 public class PersonTest1 {
 public static void main(String[] args) {
 Class<Person> personClass = Person.class;
 
 
 Method[] declaredMethods = personClass.getDeclaredMethods();
 for (Method m : declaredMethods) {
 
 Annotation[] annotations = m.getAnnotations();
 for (Annotation annotation : annotations) {
 System.out.println(annotation);
 }
 
 
 int modifiers = m.getModifiers();
 System.out.print(Modifier.toString(modifiers) + "\t");
 
 
 Class<?> returnType = m.getReturnType();
 System.out.print(returnType + "\t");
 
 
 String name = m.getName();
 System.out.print(name + "(");
 
 
 Class<?>[] parameterTypes = m.getParameterTypes();
 if(parameterTypes!=null && parameterTypes.length > 0){
 for (int i = 0; i < parameterTypes.length; i++) {
 
 String typeName = parameterTypes[i].getTypeName();
 
 String parameName = "arge_" + i;
 if(i == parameterTypes.length - 1){
 System.out.print(typeName + " " + parameName);
 break;
 }
 System.out.print(typeName + " " + parameName + ",");
 }
 }
 
 System.out.print(")" + "\t");
 
 
 Class<?>[] exceptionTypes = m.getExceptionTypes();
 if(exceptionTypes != null && exceptionTypes.length > 0){
 System.out.print("throws" + "\t");
 for (int i = 0; i < exceptionTypes.length; i++) {
 
 String exceptionName = exceptionTypes[i].getName();
 if(i == exceptionTypes.length - 1){
 System.out.print(exceptionName);
 break;
 }
 System.out.print(exceptionName + ",");
 }
 }
 System.out.println();
 }
 }
 }
 
 | 
获取运行时类的构造器
- getConstructors()获取当前运行时类的public的构造器
- getDeclaredConstructors()获取当前运行时类的所有声明的构造器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | package com.songzx.person;
 import java.lang.reflect.Constructor;
 
 
 
 
 
 public class PersonTest2 {
 public static void main(String[] args) {
 Class<Person> personClass = Person.class;
 
 
 Constructor<?>[] constructors = personClass.getConstructors();
 for (Constructor<?> constructor : constructors) {
 System.out.println(constructor);
 }
 
 
 Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
 for (Constructor<?> declaredConstructor : declaredConstructors) {
 System.out.println(declaredConstructor);
 }
 }
 }
 
 | 
获取运行时类的父类
- getSuperclass获取当前运行时类的父类
- getGenericSuperclass获取带泛型的父类
- ParameterizedType paramType = (ParameterizedType) genericSuperclass;强转带泛型的父类- 
- paramType.getActualTypeArguments()获取泛型数组
 
| 12
 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
 
 | package com.songzx.person;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 
 
 
 
 
 
 public class PersonTest3 {
 public static void main(String[] args) {
 Class<Person> personClass = Person.class;
 
 Class<? super Person> superclass = personClass.getSuperclass();
 System.out.println(superclass);
 
 
 Type genericSuperclass = personClass.getGenericSuperclass();
 
 ParameterizedType paramType = (ParameterizedType) genericSuperclass;
 System.out.println(paramType);
 
 Type[] actualTypeArguments = paramType.getActualTypeArguments();
 for (Type actualTypeArgument : actualTypeArguments) {
 
 System.out.println(actualTypeArgument.getTypeName());
 }
 }
 }
 
 | 
获取运行时类所实现的接口
- getInterfaces获取运行时类实现的接口
- personClass.getSuperclass().getInterfaces()获取父类所实现的接口
- getPackage获取运行时类所在包
- getAnnotations获取运行时类所声明的注解
| 12
 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.songzx.person;
 import java.lang.annotation.Annotation;
 
 
 
 
 
 
 public class PersonTest4 {
 public static void main(String[] args) {
 Class<Person> personClass = Person.class;
 
 Class<?>[] interfaces = personClass.getInterfaces();
 for (Class<?> anInterface : interfaces) {
 System.out.println(anInterface);
 }
 
 
 Class<?>[] interfaces1 = personClass.getSuperclass().getInterfaces();
 for (Class<?> aClass : interfaces1) {
 System.out.println(aClass);
 }
 
 
 Package pack = personClass.getPackage();
 System.out.println(pack);
 
 
 Annotation[] annotations = personClass.getAnnotations();
 for (Annotation annotation : annotations) {
 System.out.println(annotation);
 }
 }
 }
 
 | 
设置运行时类中的属性值
- personClass.getField("id")获取类中声明为 public 的属性
- personClass.getDeclaredField("name")获取类中所有声明过的属性- 
- name.setAccessible(true);该方法保证这个属性是可以访问的,通过上面的方法获取到属性后需要设置这个方法
 
| 12
 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
 
 | package com.songzx.person;import org.junit.Test;
 import java.lang.reflect.Field;
 
 
 
 
 
 
 public class PersonTest5 {
 @Test
 public void test1() throws Exception{
 
 Class<Person> personClass = Person.class;
 
 Person p = personClass.newInstance();
 
 Field id = personClass.getField("id");
 
 id.set(p,1001);
 
 System.out.println(id.get(p));
 }
 
 
 @Test
 public void test2() throws Exception{
 
 Class<Person> personClass = Person.class;
 
 Person p = personClass.newInstance();
 
 Field name = personClass.getDeclaredField("name");
 
 name.setAccessible(true);
 
 name.set(p,"Tome");
 
 System.out.println(name.get(p));
 }
 }
 
 | 
调用运行时类的静态方法
- personClass.getDeclaredMethod("showDesc", String.class);获取指定类的方法,并声明参数类型。参数类型要是一个对象
- invoke调用返回的方法值身上的 invoke 方法触发该方法- 
- 参数1(必填):指明要调用那个对象身上的方法
- 参数2:传入可变形参
 
| 12
 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.songzx.person;import java.lang.reflect.Method;
 
 
 
 
 
 
 public class PersonTest6 {
 public static void main(String[] args) throws Exception{
 
 Class<Person> personClass = Person.class;
 
 Person p = personClass.newInstance();
 
 Method showDesc = personClass.getDeclaredMethod("showDesc", String.class);
 
 showDesc.setAccessible(true);
 
 Object desc = showDesc.invoke(p, "工单描述");
 
 System.out.println(desc);
 
 
 Method info_private = personClass.getDeclaredMethod("info_private", String.class, int.class);
 info_private.setAccessible(true);
 Object tome = info_private.invoke(p, "China", 15);
 System.out.println(tome);
 
 
 Method showAge = personClass.getDeclaredMethod("showAge");
 showAge.setAccessible(true);
 
 
 Object invoke = showAge.invoke(null);
 System.out.println(invoke);
 }
 }
 
 | 
调用运行时类构造器
getDeclaredConstructor 调用指定参数的构造器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | package com.songzx.person;
 import java.lang.reflect.Constructor;
 
 
 
 
 
 
 public class PersonTest7 {
 public static void main(String[] args) throws Exception{
 
 Class<Person> personClass = Person.class;
 
 Constructor<Person> constructor = personClass.getDeclaredConstructor(String.class);
 
 constructor.setAccessible(true);
 
 Person p = constructor.newInstance("Tome");
 
 System.out.println(p);
 }
 }
 
 |