Java的反射
Java的反射
Class类
在此之前,我们必须知道一句话,“java之中的一切都可以看作一个对象”。类是对象的抽象,而Class则是类的抽象,即任何一个类都是Class的实例对象。另外注意区别Class类和class关键字。Class类下面有很多方法,例如getConstructors() (包括其一些相似作用的方法这里以及后面不再列举,例如getDeclaredConstructor()等等),getFields(),getMethods();而它们会分别返回Constructor类型、Filed类型、Method类型的对象或者数组。Class类的构造方法是私有的,当一个类被加载时,JVM(java虚拟机)会自动通过Class的私有构造方法实例化一个Class对象,而我们没有办法通过Class的构造方法去实例化Class。而我们可以通过以下三种方法来获得Class的实例化对象;
- 类名.forName(“具体路径 包名.类名”);
- 类名.class;
- 对象.getClass();
获得了Class的实例化对象,我们就可以获得类的很多信息,例如权限修饰符,参数列表,类名,成员变量,成员方法等等。
Constructor类
每个Constructor对象都代表一个构造方法,利用Constructor对象可以操作相应的构造方法。下面时Constructor类常用的方法以及它的作用;
- isVarArgs(),查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false;方法原型:public boolean isVarArgs();
- getName(),以字符串的形式返回该构造方法的名字。方法原型:public String getName();
- getParameterTypes(),按照声明顺序以Class数组的形式获得该构造方法的各个参数类型。方法原型:public Class<?>[] getParameterTypes();
- getExceptionTypes(),以Class数组的形式获得该构造方法可能抛出的异常类型。方法原型:public Class<?>[] getExceptionTypes();
- newInstance(),通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法。函数原型:public T newInstance(Object… initargs),T表示返回的是一个Objec类的对象;
注:Class.newInstance和Constructor.newInstance的有区别;Constructor的该方法能够使用有参数的构造方法,而Class下的该方法只能够使用无参默认构造方法。
- setAccessible(),如果该构造方法的权限为private,默认不允许通过反射利用newInstance()方法创建对象;如果先执行该方法并将入口参数设为true,则允许创建。方法原型:public void setAccessible(boolean flag);
7.getModifiers(),获得可以解析出该构造方法所采用的修饰符的整数(利用Modifier类下的toString方法可以转换成字符串)。方法原型:public int getModifiers()。
下面介绍几个Modifier类常用的方法;
isPublic(int mod);
isProtected(int mod);
isPrivate(int mod);
isStatic(int mod);
isFinal(int mod);
toString(int mod);
这几种方法的作用都显而易见,不再赘述。
下面看代码示例:
//代码示例 Main类
import java.lang.reflect.*;
public class Main_01 {
public static void main(String[] args) {
Example_01 example = new Example_01("10", "20", "30");
Class<? extends Example_01> exampleC = example.getClass();
Constructor[] declaredConstructors = exampleC.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
Constructor<?> constructor = declaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[] parameterTypes = constructor.getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为:");
Class[] exceptionTypes = constructor.getExceptionTypes();
for (int j = 0; j < exceptionTypes.length; j++) {
System.out.println(" " + exceptionTypes[j]);
}
Example_01 example2 = null;
while (example2 == null) {
try {
if (i == 2)
example2 = (Example_01) constructor.newInstance();
else if (i == 1)
example2 = (Example_01) constructor.newInstance("7", 5);
else {
Object[] parameters = new Object[] { new String[] {
"100", "200", "300" } };
example2 = (Example_01) constructor
.newInstance(parameters);
}
} catch (Exception e) {
System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
constructor.setAccessible(true);
}
}
if(example2!=null){
example2.print();
System.out.println();
}
}
}
}
//代码示例 Example类
public class Example_01 {
String s;
int i, i2, i3;
private Example_01() {
}
protected Example_01(String s, int i) {
this.s = s;
this.i = i;
}
public Example_01(String... strings) throws NumberFormatException {
if (0 < strings.length)
i = Integer.valueOf(strings[0]);
if (1 < strings.length)
i2 = Integer.valueOf(strings[1]);
if (2 < strings.length)
i3 = Integer.valueOf(strings[2]);
}
public void print() {
System.out.println("s=" + s);
System.out.println("i=" + i);
System.out.println("i2=" + i2);
System.out.println("i3=" + i3);
}
}
这是运行结果截图:
Filed类
每个Field对象都代表一个成员变量,利用Field对象可以操控相应的成员变量。下面是Field类的一些常用的方法以及作用;
- getName(),获得该成员变量的名称。方法原型:public String getName();
- getType(),获得表示该成员变量类型的Class对象。方法原型:public Class<?> getType();
- getModifiers(),获得可以解析出该成员变量所采用修饰符的整数。方法原型:public int getModifiers();
- get(Object obj),获得指定对象obj中成员变量的值,返回类型为Object型。方法原型:public Object get(Object obj);
- set(Object obj,Object value),将指定对象obj中成员变量的值设定为value;
还有具体到各种类型的get set方法,不再一一介绍。另外说明:Object对象指的是已经实例化的反射对象。
下面是代码示例:
//代码示例 Main类
import java.lang.reflect.*;
public class Main_02 {
public static void main(String[] args) {
Example_02 example = new Example_02();
Class exampleC = example.getClass();
// 获得所有成员变量
Field[] declaredFields = exampleC.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i]; // 遍历成员变量
// 获得成员变量名称
System.out.println("名称为:" + field.getName());
Class fieldType = field.getType(); // 获得成员变量类型
System.out.println("类型为:" + fieldType);
boolean isTurn = true;
while (isTurn) {
// 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
try {
isTurn = false;
// 获得成员变量值
System.out.println("修改前的值为:" + field.get(example));
// 判断成员变量的类型是否为int型
if (fieldType.equals(int.class)) {
System.out.println("利用方法setInt()修改成员变量的值");
field.setInt(example, 168); // 为int型成员变量赋值
// 判断成员变量的类型是否为float型
} else if (fieldType.equals(float.class)) {
System.out.println("利用方法setFloat()修改成员变量的值");
// 为float型成员变量赋值
field.setFloat(example, 99.9F);
// 判断成员变量的类型是否为boolean型
} else if (fieldType.equals(boolean.class)) {
System.out.println("利用方法setBoolean()修改成员变量的值");
// 为boolean型成员变量赋值
field.setBoolean(example, true);
} else {
System.out.println("利用方法set()修改成员变量的值");
// 可以为各种类型的成员变量赋值
field.set(example, "MWQ");
}
// 获得成员变量值
System.out.println("修改后的值为:" + field.get(example));
} catch (Exception e) {
System.out.println("在设置成员变量值时抛出异常,"
+ "下面执行setAccessible()方法!");
field.setAccessible(true); // 设置为允许访问
isTurn = true;
}
}
System.out.println();
}
}
}
//代码示例 Example类
public class Example_02 {
int i;
public float f;
protected boolean b;
private String s;
}
下面是运行结果:
Method类
每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。下面是Method类的一些常用的方法以及作用;
- getName(),获得该方法的名称。方法原型:public String getName();
- getParameterTypes(),按照声明的顺序以Class数组的形式获得该方法的各个参数的类型。方法原型:public Class<?>[] getParameterTypes();
- getReturnType(),以Class对象的形式返回该方法的返回类型。方法原型:public Class<?> getReturnType();
- getExceptionTypes(),以Class数组的形式获得该方法可能抛出的异常。方法原型:public Class<?> getExceptionTypes();
- invoke(Object obj,Object···args),利用指定参数args执行指定对象obj中的该方法,返回值类型为Object型。方法原型:public Object invoke(Object obj, Object… args);
- isVarArgs(),同Constructor;
- getModifiers(),同上。
下面是代码示例:
//代码示例 Main类
import java.lang.reflect.*;
public class Main_03 {
public static void main(String[] args) {
Example_03 example = new Example_03();
Class exampleC = example.getClass();
// 获得所有方法
Method[] declaredMethods = exampleC.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i]; // 遍历方法
System.out.println("名称为:" + method.getName()); // 获得方法名称
System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
System.out.println("入口参数类型依次为:");
// 获得所有参数类型
Class[] parameterTypes = method.getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
// 获得方法返回值类型
System.out.println("返回值类型为:" + method.getReturnType());
System.out.println("可能抛出的异常类型有:");
// 获得方法可能抛出的所有异常类型
Class[] exceptionTypes = method.getExceptionTypes();
for (int j = 0; j < exceptionTypes.length; j++) {
System.out.println(" " + exceptionTypes[j]);
}
boolean isTurn = true;
while (isTurn) {
// 如果该方法的访问权限为private,则抛出异常,即不允许访问
try {
isTurn = false;
if("staticMethod".equals(method.getName()))
method.invoke(example); // 执行没有入口参数的方法
else if("publicMethod".equals(method.getName()))
System.out.println("返回值为:"
+ method.invoke(example, 168)); // 执行方法
else if("protectedMethod".equals(method.getName()))
System.out.println("返回值为:"
+ method.invoke(example, "7", 5)); // 执行方法
else if("privateMethod".equals(method.getName())) {
Object[] parameters = new Object[] { new String[] {
"M", "W", "Q" } }; // 定义二维数组
System.out.println("返回值为:"
+ method.invoke(example, parameters));
}
} catch (Exception e) {
System.out.println("在执行方法时抛出异常,"
+ "下面执行setAccessible()方法!");
method.setAccessible(true); // 设置为允许访问
isTurn = true;
}
}
System.out.println();
}
}
}
//代码示例 Example
public class Example_03 {
static void staticMethod() {
System.out.println("执行staticMethod()方法");
}
public int publicMethod(int i) {
System.out.println("执行publicMethod()方法");
return i * 100;
}
protected int protectedMethod(String s, int i)
throws NumberFormatException {
System.out.println("执行protectedMethod()方法");
return Integer.valueOf(s) + i;
}
private String privateMethod(String... strings) {
System.out.println("执行privateMethod()方法");
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < strings.length; i++) {
stringBuffer.append(strings[i]);
}
return stringBuffer.toString();
}
}
下面是运行结果图:
未完待更……2020-4-2