反射
1. 反射
1.1 Java代码和Java文件
Java代码基本格式
1. Java代码都在类内或者接口内
2.
class 类名 {
成员变量
构造方法
成员方法
Annotation 注解
}
Java文件要求:
1. 通常情况下一个Java文件对应一个Java类
2. Java文件包含当前Java代码的所有内容!!!
1.2 Java文件和.class字节码文件
Java文件
FirstJava.java
通过编译器 javac ==> javac FirstJava.java ==> FirstJava.class
.class字节码文件是什么???
二进制可执行文件。
.class字节码文件中会包含Java文件的所有内容。
.class字节码文件包含Java程序的所有可执行内容(注释不参与编译和执行)。
1.3 .class字节码文件在内存中的位置
1.4 .class字节码文件和Java代码关系
1.5 Class类相关方法
Class Class. forName ( String packageNameAndClassName) throws ClassNotFoundException;
根据完整的包名. 类名获取对应的Class类对象
ClassNotFoundException 未找到指定类
Class 类对象. getClass ( ) ;
通过类对象获取当前类对象对应的Class类对象
例如:
Person p = new Person ( ) ; p. getClass ( ) == > Person类对应Class对象
Class 类名. class ;
通过类名获取当前类对应属性 Class对象
例如:
Person. class == > Person类对应Class对象。
package com. qfedu. a_reflect;
public class GetClassObject {
public static void main ( String[ ] args) throws ClassNotFoundException {
Class cls1 = Class. forName ( "com.project.a_reflect.Person" ) ;
Person person = new Person ( ) ;
Class cls2 = person. getClass ( ) ;
Class cls3 = Person. class ;
System. out. println ( "cls1 == cls2 : " + ( cls1 == cls2) ) ;
System. out. println ( "cls2 == cls3 : " + ( cls2 == cls3) ) ;
System. out. println ( "cls3 == cls1 : " + ( cls3 == cls1) ) ;
}
}
1.6 操作Constructor 构造方法类
1.6.1 通过Class类对象获取对应类的Constructor构造方法类对象
Constructor[ ] getConstructors ( ) ;
获取当前Class对象对应类中所有非私有化构造方法类对象数组。
Constructor[ ] getDeclaredConstructors ( ) ;
【暴力反射】
获取当前Class对象对应类中的所有构造方法类对象数组,包括私有化构造方法。
Constructor getConstructor ( Class. . . parameterTypes) ;
获取当前Class对象中,指定参数数据类型的构造方法。获取的构造方法为非私有化构造方法
Class. . . parameterTypes
Class类型不定长参数,用于约束当前构造方法对应的数据类型。
例如:
无参数构造方法
cls. getConstructor ( ) ; == > Person ( ) ;
两个参数构造方法( int , String)
cls. getConstructor ( int . class , String. class ) == > Person ( int , String)
Constructor getDeclaredConstructor ( Class. . . parameterTypes) ;
【暴力反射】
获取当前Class对象中,指定数据类型的构造方法,包括私有化构造方法
例如:
获取私有化String类型构造方法
cls. getDeclaredConstructor ( String. class ) == > private Person ( String. class )
1.6.2 操作Constructor类对象创建对应类对象
Object newInstance ( Object. . . parameters) ;
通过Constructor类对象,执行对应的构造方法,创建对应类对象
Object. . . 不定长参数,要求数据类型为Object类型。
例如:
Person ( ) ; 无参数构造方法
Person p1 = ( Person) constructor. newInstance ( ) ;
Person ( int , java. lang. String) ;
Person p2 = ( Person) constructor. newInstance ( 10 , "Java真好学" ) ;
package com. qfedu. a_reflect;
import java. lang. reflect. Constructor;
import java. lang. reflect. InvocationTargetException;
public class GetConstructorObject {
public static void main ( String[ ] args)
throws ClassNotFoundException, NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Class cls = Class. forName ( "com.project.a_reflect.Person" ) ;
Constructor[ ] constructors = cls. getConstructors ( ) ;
for ( Constructor constructor : constructors) {
System. out. println ( constructor) ;
}
System. out. println ( ) ;
Constructor[ ] declaredConstructors = cls. getDeclaredConstructors ( ) ;
for ( Constructor constructor : declaredConstructors) {
System. out. println ( constructor) ;
}
System. out. println ( ) ;
Constructor constructor1 = cls. getConstructor ( ) ;
Constructor constructor2 = cls. getConstructor ( int . class ) ;
Constructor constructor3 = cls. getConstructor ( int . class , String. class ) ;
System. out. println ( constructor1) ;
System. out. println ( constructor2) ;
System. out. println ( constructor3) ;
Constructor constructor4 = cls. getDeclaredConstructor ( String. class ) ;
System. out. println ( constructor4) ;
System. out. println ( ) ;
Person p1 = ( Person) constructor1. newInstance ( ) ;
Person p2 = ( Person) constructor2. newInstance ( 10 ) ;
Person p3 = ( Person) constructor3. newInstance ( 20 , "张三爱Java" ) ;
System. out. println ( p1) ;
System. out. println ( p2) ;
System. out. println ( p3) ;
constructor4. setAccessible ( true ) ;
Person p4 = ( Person) constructor4. newInstance ( "Java快乐多" ) ;
System. out. println ( p4) ;
}
}
1.7 操作 Method 成员方法类
1.7.1 通过Class类对象获取对应类的Method成员方法类对象
Method[ ] getMethods ( ) ;
通过Class类对象调用,获取当前类内的所有非私有化成员方法,包含从父类继承而来子类可以使用的非私有化方法。
Method[ ] getDeclaredMethods ( ) ;
【暴力反射】
通过Class类对象调用,获取当前类内的所有成员方法,包括私有化成员方法,但是不包括从父类继承而来的方法。
Method getMethod ( String methodName, Class. . . parameterTypes) ;
通过Class类对象调用,根据方法名称和对应的形式参数列表数据类型获取对应的成员方法,可以获取父类继承方法,不能获取私有化成员方法
例如:
无参数成员方法 获取 game ( ) ;
cls. getMethod ( "game" ) ;
有参数成员方法 获取 game ( String) ;
cls. getMethod ( "game" , String. class ) ;
Method getDeclaredMethod ( String methodName, Class. . . parameterTypes) ;
通过Class类对象调用,根据方法名称和对应的形式参数列表数据类型获取对应的成员方法,可以获取私有化成员方法,不能获取父类成员方法。
例如:
无参数私有化成员方法 testPrivate ( ) ;
cls. getDeclaredMethod ( "testPrivate" ) ;
有参数私有化成员方法 testPrivate ( String) ;
cls. getDeclaredMethod ( "testPrivate" , String. class ) ;
1.7.2 操作Method类对象执行方法
Object invoke ( Object obj, Object. . . parameters) ;
通过Method类对象调用,执行对应方法。
Object obj 执行当前方法的类对象。
Object. . . parameters 对应当前方法的实际参数列表
package com. qfedu. a_reflect;
import java. lang. reflect. InvocationTargetException;
import java. lang. reflect. Method;
public class GetMethodObject {
public static void main ( String[ ] args)
throws ClassNotFoundException, SecurityException, NoSuchMethodException,
InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Class cls = Class. forName ( "com.project.a_reflect.Person" ) ;
Method[ ] methods = cls. getMethods ( ) ;
for ( Method method : methods) {
System. out. println ( method) ;
}
System. out. println ( ) ;
Method[ ] declaredMethods = cls. getDeclaredMethods ( ) ;
for ( Method method : declaredMethods) {
System. out. println ( method) ;
}
System. out. println ( ) ;
Method game1 = cls. getMethod ( "game" ) ;
Method game2 = cls. getMethod ( "game" , String. class ) ;
System. out. println ( game1) ;
System. out. println ( game2) ;
System. out. println ( ) ;
Method testPrivate1 = cls. getDeclaredMethod ( "testPrivate" ) ;
Method testPrivate2 = cls. getDeclaredMethod ( "testPrivate" , String. class ) ;
System. out. println ( testPrivate1) ;
System. out. println ( testPrivate2) ;
System. out. println ( ) ;
Object object = cls. getConstructor ( ) . newInstance ( ) ;
game1. invoke ( object) ;
game2. invoke ( object, "World Of Tank" ) ;
testPrivate1. setAccessible ( true ) ;
testPrivate2. setAccessible ( true ) ;
testPrivate1. invoke ( object) ;
testPrivate2. invoke ( object, "西红柿+黄瓜+鸡蛋+羊肉串" ) ;
}
}
1.8 操作 Field 成员变量类
1.8.1 通过Class类对象获取对应类的Field成员变量类对象
Field[ ] getFields ( ) ;
获取类内所有非私有化成员变量数组
Field[ ] getDeclaredFields ( ) ;
【暴力反射】
获取类内所有成员变量数组,包括私有化成员变量
Field getField ( String fieldName) ;
根据成员变量名字获取对应的成员变量对象,要求当前成员变量非私有化
例如:
public int test;
cls. getField ( "test" ) ;
Field getDeclaredField ( String fieldName) ;
【暴力反射】
获取类内指定名字的成员变量对象,包括私有化成员变量
例如:
private String name;
private int id;
cls. getDeclaredField ( "name" ) ;
cls. getDeclaredField ( "id" ) ;
1.8.2 操作Field类对象赋值取值成员变量
void set(Object obj, Object value);
赋值Field类对象对应成员变量
Object obj 明确当前赋值的成员变量是哪一个类对象的。
Object value 给予当前成员变量赋值使用数据
Before:
Person p = new Person();
p.setName("老王");
Now:
name.set(p, "老王");
Object get(Object obj);
取值Field类对象对应成员变量
Object obj 明确获取的成员变量对应数据是哪一个类对象
Before
Person p = new Person();
p.getName(); ==> 老王
name.get(p); ==> 老王
package com. qfedu. a_reflect;
import java. lang. reflect. Field;
import java. lang. reflect. InvocationTargetException;
public class GetFieldObject {
public static void main ( String[ ] args)
throws ClassNotFoundException, NoSuchFieldException, SecurityException,
InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException {
Class cls = Class. forName ( "com.project.a_reflect.Person" ) ;
Field[ ] fields = cls. getFields ( ) ;
for ( Field field : fields) {
System. out. println ( field) ;
}
System. out. println ( ) ;
Field[ ] declaredFields = cls. getDeclaredFields ( ) ;
for ( Field field : declaredFields) {
System. out. println ( field) ;
}
System. out. println ( ) ;
Field test = cls. getField ( "test" ) ;
System. out. println ( test) ;
System. out. println ( ) ;
Field id = cls. getDeclaredField ( "id" ) ;
Field name = cls. getDeclaredField ( "name" ) ;
System. out. println ( id) ;
System. out. println ( name) ;
System. out. println ( ) ;
Object obj = cls. getConstructor ( ) . newInstance ( ) ;
System. out. println ( obj) ;
test. set ( obj, 100 ) ;
System. out. println ( obj) ;
System. out. println ( test. get ( obj) ) ;
id. setAccessible ( true ) ;
name. setAccessible ( true ) ;
id. set ( obj, 10 ) ;
name. set ( obj, "大哥好威武" ) ;
System. out. println ( obj) ;
System. out. println ( id. get ( obj) ) ;
System. out. println ( name. get ( obj) ) ;
System. out. println ( ) ;
System. out. println ( id. getType ( ) ) ;
System. out. println ( name. getType ( ) ) ;
}
}
1.9 暴力反射授权
class AccessibleObject 类内方法
public static void setAccessible ( AccessibleObject[ ] array, boolean flag) ;
通过类名调用的静态工具方式,给予AccessibleObject类对象或者其子类对象数组,赋值操作权限。
子类对象包括: Field Method Constructor
public void setAccessible ( boolean flag) ;
通过AccessibleObject类对象调用,单一权限授权,Field Method Constructor都可以使用。
1.10 案例操作
需要使用
1. String方法
2. IO流 推荐字符流操作
3. 反射
4. 自行了解 ==> String 转其他类型方法 百度 parse系列方法
文件名:
studentInfo.txt
文件内容:
className=com.qfedu.a_reflect.Student
name=李四
age=18
gender=false
javaScore=59
webScore=59
dbScore=59
目标
文件内容转Student类对象
package com. qfedu. a_reflect;
import java. io. BufferedReader;
import java. io. FileReader;
import java. io. IOException;
import java. lang. reflect. Field;
import java. lang. reflect. InvocationTargetException;
import java. util. Arrays;
@SuppressWarnings ( "all" )
public class ReflectDemo {
public static void main ( String[ ] args)
throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException, NoSuchFieldException {
BufferedReader br = new BufferedReader ( new FileReader ( "./data/studentInfo.txt" ) ) ;
String classInfo = br. readLine ( ) ;
String className = classInfo. substring ( classInfo. indexOf ( "=" ) + 1 ) ;
Class cls = Class. forName ( className) ;
Object obj = cls. getConstructor ( ) . newInstance ( ) ;
String info = null;
Object value = null;
while ( ( info = br. readLine ( ) ) != null) {
String[ ] split = info. split ( "=" ) ;
System. out. println ( Arrays. toString ( split) ) ;
Field field = cls. getDeclaredField ( split[ 0 ] ) ;
field. setAccessible ( true ) ;
Class type = field. getType ( ) ;
if ( type. equals ( String. class ) ) {
value = split[ 1 ] ;
} else if ( type. equals ( int . class ) ) {
value = Integer. parseInt ( split[ 1 ] ) ;
} else if ( type. equals ( boolean . class ) ) {
value = Boolean. parseBoolean ( split[ 1 ] ) ;
}
field. set ( obj, value) ;
}
System. out. println ( obj) ;
br. close ( ) ;
}
}