基本概念

  • 通常情况下编写代码都是固定的,无论运行多少次执行的结果也是固定的,在某些特殊场合中编写代码时不确定要创建什么类型的对象,也不确定要调用什么样的方法,这些都希望通过运行时传递的参数来决定,该机制叫做动态编程技术,也就是反射机制。
  • 通俗来说,反射机制就是用于动态创建对象并且动态调用方法的机制。
  • 目前主流的框架底层都是采用反射机制实现的。
  • 如:
    Person p= new Person(); //表示声明 Person类型的引用指向 Person类型的对象
    p.show(); // 表示调用 Person类中的成员方法show

Class类

甚本概念

  • java.lang.Class类的实例可以用于描述java应用程序中的类和接口,也就是一种数据类型。
  • 该类没有公共构造方法,该类的实例由java虚拟机和类加载器自动构造完成,本质上就是加载到内存中的运行时类。

    获取 Class对象的方式

  • 使用数据类型.class的方式可以获取对应类型的 Class对象
  • 使用引用/对象.getClass()的方式可以获取对应类型的Class对象。
  • 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象
  • 使用 Class.forName 的方式来获取参数指定类型的Class象
  • 使用类加载器 ClassLoader 的方式获取指定类型的Class对象

常用方法

方法声明功能介绍
static Class< ? > forName(String className)用于获取参数指定类型对应的class对象并返回
T newInstance()(已过时 请使用Constructor类)用于创建该Cass对象所表示类的新实例

Constructor类

基本概念

  • java.lang.reflect.Constructor类主要用于描述获取到的构造方法信息。

    Class类的常用方法

    方法声明功能介绍
    Constructor< T > getConstructor( Class< ? >…parrmeterTypes)用于获取此Class对象所表示类型中参数指定的公共构造方法
    Constructor< ? > [] getConstructors()用于获取此Class对象所表示类型中所有的公共构造

Constructor类的常用方法

方法声明功能介绍
T newInstance(object…initargs)使用此 Constructor对象描述的构造方法来构造Cass对象代表类型的新实例
int getModifiers()获取方法的访问修饰符
String getName()获取方法的名称
Class< ? >[] getParameterType()获取方法所有参数的类型

使用反射机制创建实例

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
import java.io.*;
import java.lang.reflect.Constructor;

public class PersonTest {
public static void main(String[] args) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
// 文件字节输入流
fis = new FileInputStream("./config.txt");
// 将文件字节输入流转换为 Reader 输入流
isr = new InputStreamReader(fis);
// 使用字符缓冲加载输入流
br = new BufferedReader(isr);
// 获取配置文件第一行
String line = br.readLine();
// 将配置文件中的类动态加载
Class forName = Class.forName(line);
System.out.println("动态加载的类为:" + forName); // class task4.reflect.Person
// 获取Class对象的无参构造方法,也就是Person的无参构造方法
Constructor constructor = forName.getConstructor();
// 使用获取到的无参构造方法构造相应类型的对象也就是Person类型的对象
System.out.println("使用无参构造的对象是:" + constructor.newInstance());
// 通过有参构造获取对象 按传入参数选择对应的构造
Constructor constructor1 = forName.getConstructor(int.class, String.class);
System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10,"feng"));

} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != fis) {
fis.close();
}
if (null != isr) {
isr.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}

}
}

Field 类

基本概念

java.lang.reflect.Field类主要用于描述获取到的单个成员变量信息。

Class类的常用方法

方法声明功能介绍
Field getDeclaredField(String name)用于获取此Cas对所表示类中参数指定的单个成员变量信息
Field getDeclaredFields()用于获取此Class对象所表示类中所有成员变量信息

Field类的常用方法

方法声明功能介绍
Object get(Object obj)取参数对象Object中此Field对象所表示成员变量的数值
void set(Object obj, Object value)将参数对象Object中此Field对象表示成员变量的数值修改为参数vlaue的数值
void setAccessible(boolean flag)当实参传通true时,则反射对象在使用时应该取消Java语言访问检查
int getModifiers()获取成员变量的访问修饰符
Class< ? > getType()获取成员变量的数据类型
String 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
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class PersonTest {
public static void main(String[] args) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
// 文件字节输入流
fis = new FileInputStream("./config.txt");
// 将文件字节输入流转换为 Reader 输入流
isr = new InputStreamReader(fis);
// 使用字符缓冲加载输入流
br = new BufferedReader(isr);
// 获取配置文件第一行
String line = br.readLine();
// 将配置文件中的类动态加载
Class forName = Class.forName(line);
// 通过有参构造获取对象 按传入参数选择对应的构造
Constructor constructor1 = forName.getConstructor(int.class, String.class);
System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10, "feng"));

// 有参构造创建对象
Object object = constructor1.newInstance(10, "feng");
// 获取成员变量
Field field = forName.getDeclaredField("name");
// 获取对象 object 中名字为 filed 的数值,也就是成员变量name中的值
// 如果是private没有权限访问 异常,需要反射时调用setAccessible(true);取消java访问检查
field.setAccessible(true); // 取消 java 访问检查
Object v = field.get(object);
System.out.println("获取到成员变量的值为:" + v);

// 修改成员变量
field.set(object, "li");
v = field.get(object);
System.out.println("修改后的成员变量值为:" + v);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != fis) {
fis.close();
}
if (null != isr) {
isr.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}

}
}

Method类

基本概念

java.lang.reflect.Method类主要用于描述获取到的个成员方法信息。

Class类的常用方法

方法声明功能介绍
Method getMethod(String name, Class< ? >…parameterTypes)用于获取该Class对象表示类中名字为name参数为parameterTypes的指定公共成员方法
Method getMethods()用于获取该Cass对象表示类中所有公共成员方法

Method类的常用方法

方法声明功能介绍
Object invoke(Object obj, Object…args)使用对象obj来调用此 Method对象所表示的成员方法,实参传递args
int getModifiers()获取方法的访问修饰符
Class< ? > getReturnType()获取方法的返回值类型
String getName()获取方法的名称
Class< ? > getParameterTypes()获取方法所有参数的类型
Class< ? > 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
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PersonTest {
public static void main(String[] args) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
// 文件字节输入流
fis = new FileInputStream("./config.txt");
// 将文件字节输入流转换为 Reader 输入流
isr = new InputStreamReader(fis);
// 使用字符缓冲加载输入流
br = new BufferedReader(isr);
// 获取配置文件第一行
String line = br.readLine();
// 将配置文件中的类动态加载
Class forName = Class.forName(line);
// 通过有参构造获取对象 按传入参数选择对应的构造
Constructor constructor1 = forName.getConstructor(int.class, String.class);
System.out.println("使用有参构造获取到的对象是:" + constructor1.newInstance(10, "feng"));

// 有参构造创建对象
Object object = constructor1.newInstance(10, "feng");
// 获取方法有参方法
Method setName = forName.getMethod("setName", String.class);
// 获取无参方法
Method getName = forName.getMethod("getName");
// 调用方法
setName.invoke(object, "Hello");
Object invoke = getName.invoke(object);
System.out.println("获取到的值为:" + invoke);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != fis) {
fis.close();
}
if (null != isr) {
isr.close();
}
if (null != br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}

}
}

获取其它结构信息

方法声明功能介绍
Package getPackage()获取所在的包信息
Class< ? super T > getSuperClass()获取继承的父类信息
Class< ? >[] getInterfaces()获取实现的所有接口
Annotation[] getAnnotations()获取注解信息
Type[] getGenericInterfaces()获取泛型信息