Java反射机制概述
- Reflection(反射)是被视为动态语言的关键,反射机智允许程序在执行期间通过 ReflectionAPI 取得任何类内部信息,并能直接操作任意对象的内部属性及方法
- 加载完类之后,在堆内部的方法区中就产生了一个Class类型的对象,一个类只有个一个Class对象,这个对象就包含了完整类的结构信息。我们通过这个对象看到类的内部结构。这个对象就像一个镜子,透过镜子看到类的内部结构,所以形象的称为“反射”
两种方式:
- 正常方式:引入需要的包类名称 -> 通过new实例化 -> 取得完整的实例
- 反射方式:实例化对象 -> getClass 方法 -> 得到完整的包类名称
Java反射机制提供的功能
- 在运行时判断任意一个对象的所属类
- 在运行时判断任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
反射类的使用
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
| 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 对应着一个运行时类
- 加载到内存中的类会缓存一段时间,在这期间我们可以通过不同的方式来获取到运行时类
获取运行时类的多种方式
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
| 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
获取
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
| 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 类的空参构造器
1 2 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(); } } }
|
体会反射带来的动态性
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
| 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()
获取属性名称
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
| 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()
获取当前运行时类声明的所有方法
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
| 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()
获取异常数组
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 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()
获取当前运行时类的所有声明的构造器
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
| 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()
获取泛型数组
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
| 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
获取运行时类所声明的注解
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.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);
该方法保证这个属性是可以访问的,通过上面的方法获取到属性后需要设置这个方法
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
| 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:传入可变形参
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.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
调用指定参数的构造器
1 2 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); } }
|