一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
1、获取Class对象
获取类对象的三种方式,1已经可以创建实体类了,再用反射,多此一举;2需要配置文件支持;3通过全限定名获取,一般常用
2获取构造器
请注意图中的修饰符和参数
@Test//获取构造器
public void objTest3() {
System.out.println("**********************************获取所有构造器**********************************");
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?>[] constructors = aClass.getConstructors();
System.out.println("**********************************获取所有公共构造器**********************************");
for (Constructor<?> constructor : constructors) {
System.out.println("构造器输出 : " + constructor);
}
System.out.println("**********************************获取所有构造器(包括私有,受保护的)**********************************");
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("构造器输出 : " + declaredConstructor);
}
System.out.println("**********************************获取默认的构造器(公有无参)**********************************");
Constructor<?> constructor = null;
try {
constructor = aClass.getConstructor(null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("构造器输出:" + constructor);
}
控制台输出结果
getConstructors 获取所有公共的构造器;getDeclaredConstructors 获取所有构造器,包括私有,受保护的
获取私有构造器,并调用
@Test//获取私有构造器并调用
public void objTest4() {
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?> declaredConstructor = null;
try {
//反射获取构造方法对象
declaredConstructor = aClass.getDeclaredConstructor(int.class);//String.class char.class int.class
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("构造方法:" + aClass);
declaredConstructor.setAccessible(true);//开启暴力访问,忽略访问修饰符
try {
//构造方法中添加属性、返回T类型
Object newInstance = declaredConstructor.newInstance(18);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
控制台输出结果
getDeclaredConstructor(int.class) 指定获取构造器,参数int
反射回的对象.setAccessible(true); 开启暴力模式,忽略修饰符
3获取成员变量
@Test//获取成员变量
public void Fields() {
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.reflexOfEntity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] fields = aClass.getFields();
System.out.println("**********************************获取公有成员变量**********************************");
for (Field field : fields) {
System.out.println("成员变量:" + field);
}
System.out.println("**********************************获取所有成员变量(包括私有、受保护、默认的)**********************************");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("成员变量:" + declaredField);
}
}
控制台输出结果
注意修饰符和成员变量名称
类对象.getFields 获取所有公有的成员变量; 类对象.getDeclaredFields 获取所有的成员变量,包括私有的,受保护的,默认的;
@Test//获取私有成员变量并调用
public void Fields2() {
System.out.println("**********************************获取私有属性并调用**********************************");
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.reflexOfEntity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("遍历所有成员变量:" + declaredField);
} //private java.lang.String com.example.reflex.reflexOfEntity.phoneNum 获取到的私有成员变量
Field phoneNum = null;
try {
phoneNum = aClass.getDeclaredField("phoneNum");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
System.out.println("输出私有成员变量:" + phoneNum);
//反射类对象
Object newInstance = null;
try {
newInstance = aClass.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
phoneNum.setAccessible(true);//开启暴力模式,忽略修饰符
try {
phoneNum.set(newInstance,"222");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
reflexOfEntity reflexOfEntity = (reflexOfEntity) newInstance;//获取类实例化对象
System.out.println("输出对象,查看phoneNum属性:" + reflexOfEntity);
}
控制台输出
私有的成员变量 phoneNum 被赋值
类对象.getConstructor().newInstance(); 获取类实例化对象
成员变量对象.set(类实例化对象,"222");
aClass.getDeclaredField("phoneNum"); aClass(类对象)phoneNum (成员变量名称)
4获取方法
@Test//获取方法
public void testMethod() {
//获取类对象
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.reflexOfMethod");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("**********************************获取所有共有方法**********************************");
//获取所有的共有方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println("共有方法:" + method);
}
System.out.println("**********************************获取所有(自定义)方法(包括私有,默认,受保护的)**********************************");
//获取所有方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("所有方法:" + declaredMethod);
}
}
控制台输出
注意方法名,修饰符,包名
getMethods();获取所有共有方法,包括Java内设方法 ; getDeclaredMethods()获取所有自定义方法,包括私有的,受保护的,默认的;
@Test//获取指定方法,并调用
public void testMethod2() {
//获取类对象
Class<?> aClass = null;
try {
aClass = Class.forName("com.example.reflex.reflexOfMethod");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("获取类对象:" + aClass);
System.out.println("**********************************获取所有(自定义)方法(包括私有,默认,受保护的)**********************************");
//获取自定义所有方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("查看方法:" + declaredMethod);
}
//public void com.example.reflex.reflexOfMethod.show1(java.lang.String)公有方法show1
//private java.lang.String com.example.reflex.reflexOfMethod.show4(int)私有方法show4
//调用指定方法
Method show1 = null;
try {
show1 = aClass.getMethod("show1", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("获得方法:" + show1);
//获取类实例化对象
Object newInstance = null;
try {
newInstance = aClass.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Object chenyb = null;
try {
chenyb = show1.invoke(newInstance, "Chenyb");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("调用方法show1,输出返回值:" + chenyb);
Method show4 = null;
try {
show4 = aClass.getDeclaredMethod("show4", int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("获得私有方法:" + show4);
//调用类对象
show4.setAccessible(true);//暴力调用,忽略修饰符
Object invoke = null;
try {
invoke = show4.invoke(newInstance, 18);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("调用方法show4,输出返回值:" + invoke);
}
控制台输出
-
以上环节,注意开启暴力权限的步奏,和参数类型 类型 类型
2018-09-05
Chenyb 随笔记录,方便自己学习(学习到了Java 线程&反射,才感觉自己java 才刚刚入门)