基本概念
- 通常情况下编写代码都是固定的,无论运行多少次执行的结果也是固定的,在某些特殊场合中编写代码时不确定要创建什么类型的对象,也不确定要调用什么样的方法,这些都希望通过运行时传递的参数来决定,该机制叫做动态编程技术,也就是反射机制。
- 通俗来说,反射机制就是用于动态创建对象并且动态调用方法的机制。
- 目前主流的框架底层都是采用反射机制实现的。
- 如:
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() |
获取方法所有参数的类型 |
使用反射机制创建实例
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() |
取成员变量的名称 |
获取和修改成员变量
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() |
获取方法的异常信息 |
获取方法及调用方法
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() |
获取泛型信息 |