JAVA中的反射,所说的意思就是我们可以在程序运行期间内,动态获取某一个Class对象的所有信息,包括修饰符(modifiers),属性(fields),方法(methods)等。
举个例子就好比家里的防盗门,各种Class对象就是来敲门的各种人,当我们获取到一个未知其内容的Class对象的时候,就好比有一个没有预约的人来敲门,此时我们无法感知门外面的人是谁,他有可能是物业,有可能是外卖小哥,也有可能是查水表的。而反射就好比门眼,我们通过反射来观察未知其内容的Class对象,就好比通过门眼来观察门外的未知的人,这时,门外人的所有信息我们就可以通过门眼知晓了,他可能是穿着黄衣服的美团小哥,也可能是蓝衣服的饿了么小哥,而且高矮胖瘦,颜值如何,尽在我们的掌握。
但是反射也会消耗系统性能、增加程序复杂度,就好比你去把门眼的时候不得不放弃你正在进行的DOTA团战一样,所以,需要在合理的情形下使用才是最好的。
我们先创建需要用到的示例Class类:
ReflectTest:
package reflecttest;
public class ReflectTest {
static{
System.out.println("ReflectTest is init");
}
public String isPublicField = "defaultPublicField";
protected String isProtectedField = "defaultprotectedField";
String isDefaultField = "defaultDefaultField";
private String isPrivateField = "defaultPrivateField";
ReflectTest() {
System.out.println("ReflectTest Constructor for no args");
}
public ReflectTest(String arg1) {
System.out.println("ReflectTest Constructor for String arg1");
}
private ReflectTest(String arg1, String arg2) {
System.out.println("ReflectTest Constructor for String arg1 and String arg2");
}
public void isReloadMethod(String arg1) {
System.out.println("isReloadMethod for String arg1");
}
private void isReloadMethod(String arg1, String arg2) {
System.out.println("isReloadMethod for String arg1 and String arg2");
}
public void isPublicMethod() {
System.out.println("isPublicMethod");
}
protected void isProtectedMethod() {
System.out.println("isProtectedMethod");
}
void isDefaultMethod() {
System.out.println("isDefaultMethod");
}
private void isPrivateMethod() {
System.out.println("isPrivateMethod");
}
public String getIsPublicField() {
return isPublicField;
}
public void setIsPublicField(String isPublicField) {
this.isPublicField = isPublicField;
}
public String getIsPrivateField() {
return isPrivateField;
}
public void setIsPrivateField(String isPrivateField) {
this.isPrivateField = isPrivateField;
}
public String getIsProtectedField() {
return isProtectedField;
}
public void setIsProtectedField(String isProtectedField) {
this.isProtectedField = isProtectedField;
}
public String getIsDefaultField() {
return isDefaultField;
}
public void setIsDefaultField(String isDefaultField) {
this.isDefaultField = isDefaultField;
}
}
1. 进行反射,首先也是必要的,就是获取Class对象,一共有三种方法:
public static void main(String[] args) {
/*
注意:这种通过 类名.class 方式来获取class对象的方式并不会初始化ReflectTest类
*/
Class c1 = ReflectTest.class;
System.out.println("=====================");
/*
当我们获取到了一个Object对象,但是我们无法确定它属于哪个对象时
我们可以通过 对象.getClass()的方式来获取这个对象的Class对象
*/
Object reflectTest = new ReflectTest();
Class c2 = reflectTest.getClass();
System.out.println("=====================");
try {
/**
* 当我们已知某个类的完整类路径名称的时候,可以通过Class.forName()方法来获取Class对象
* 但是可能会抛出 ClassNotFoundException 异常
*/
Class c3 = Class.forName("reflecttest.ReflectTest");
/*
* 每个类只会有一个class对象,因此通过以上三种方法得到的 c1、c2、c3 其实是同一个对象
* 因此互相之间equals为true
*/
System.out.println(c1.equals(c2));
System.out.println(c1.equals(c3));
System.out.println(c2.equals(c3));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
控制台打印如下:
2. 获取到Class对象后,通过Class对象获取Class内容的常用方法如下:
getName():获取类的名称(包名 . 类名)
getFields():获取类的所有public修饰的属性
getField(String name):获取类的符合指定名称的public修饰的属性,无法获取default、protected、private修饰的属性
getDeclaredFields():获取类的所有属性,包含public、protected、default、private修饰的属性
getDeclaredField(String name):获取指定名称的field属性,包含public、protected、default、private修饰的属性
getMethods():获取所有的public修饰的方法
getMethod(String name, Class<T>... parameterTypes):获取符合指定方法名称与参数列表的public修饰的方法,第一个参数为方法名称,其余后面的参数都依次为参数列表的各个参数类型
getDeclaredMethods():获取类的所有方法,包含public、protected、default、private修饰的方法
getDeclaredMethod(String name, Class<T>... parameterTypes):获取符合指定名称与参数列表的方法,包含public、protected、default、private修饰的方法,第一个参数为方法名称,其余后面的参数都依次为参数列表的各个参数类型
getConstructors():获取类的所有的public修饰的构造函数
getConstructor(Class<T>... parameterTypes):获取类的符合指定参数列表的public修饰的构造方法
getDeclaredConstructors():获取类的所有的构造函数,包含public、protected、default、private修饰的构造函数
getDeclaredConstructor(Class<T>... parameterTypes):获取类的符合指定参数列表的构造方法,包含public、protected、default、private修饰的构造方法
newInstance():通过该类的无参构造函数进行对象实例化
代码示例:
getName():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getName() 方法获取类的完整类路径名称
System.out.println(classObj.getName());
}
执行结果:
getFields():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getFields() 方法获取所有的 public 修饰符修饰的field属性
Field[] publicFields = classObj.getFields();
Arrays.stream(publicFields).forEach(System.out::println);
}
执行结果:
getField(String name):
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getField(String name) 方法获取指定名称的 public 修饰的field属性,无法获取非public修饰的field
try {
Field publicField = classObj.getField("isPublicField");
System.out.println("publicField:"+ publicField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field protectedField = classObj.getField("isProtectedField");
System.out.println("protectedField:"+ protectedField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field defaultField = classObj.getField("isDefaultField");
System.out.println("defaultField:"+ defaultField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field privateField = classObj.getField("isPrivateField");
System.out.println("privateField:"+ privateField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
执行结果:
getDeclaredFields():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getFields() 方法获取所有的 public 修饰符修饰的field属性
Field[] publicFields = classObj.getDeclaredFields();
Arrays.stream(publicFields).forEach(System.out::println);
}
执行结果:
getDeclaredFields():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getDeclaredField(String name) 方法获取指定名称的field属性,包含public、protected、default、private修饰的属性
try {
Field publicField = classObj.getDeclaredField("isPublicField");
System.out.println("publicField:" + publicField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field protectedField = classObj.getDeclaredField("isProtectedField");
System.out.println("protectedField:" + protectedField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field defaultField = classObj.getDeclaredField("isDefaultField");
System.out.println("defaultField:" + defaultField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Field privateField = classObj.getDeclaredField("isPrivateField");
System.out.println("privateField:" + privateField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
执行结果:
getMethods():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getMethods()方法会获取所有的public修饰的方法
Method[] methods = classObj.getMethods();
Arrays.stream(methods).forEach(System.out::println);
}
执行结果:
getMethod(String name, Class<T>... parameterTypes):
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Method method;
// getMethod(String name, Class<T>... parameterTypes)方法会获取符合指定名称与参数列表的public修饰的方法
try {
method = classObj.getMethod("isReloadMethod", String.class);
System.out.println("String.class(public):" + method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
method = classObj.getMethod("isReloadMethod", String.class, String.class);
System.out.println("String.class, String.class(private):" + method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
// 因为本身ReflectTest类就不具备参数列表为只接受一个Integer类型的isReloadMethod方法,所以会报出没有目标方法的异常
method = classObj.getMethod("isReloadMethod", Integer.class);
System.out.println("Integer.class(not exits):" + method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
执行结果:
getDeclaredMethods():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// getDeclaredMethods()方法会获取所有的方法
Method[] methods = classObj.getDeclaredMethods();
Arrays.stream(methods).forEach(System.out::println);
}
执行结果:
getDeclaredMethod(String name, Class<T>... parameterTypes):
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Method method;
// getDeclaredMethod(String name, Class<T>... parameterTypes)方法会获取符合指定名称与参数列表的方法
try {
method = classObj.getDeclaredMethod("isReloadMethod", String.class);
System.out.println("String.class(public):"+method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
method = classObj.getDeclaredMethod("isReloadMethod", String.class, String.class);
System.out.println("String.class, String.class(private):"+method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
// 因为本身ReflectTest类就不具备参数列表为只接受一个Integer类型的isReloadMethod方法,所以会报出没有目标方法的异常
method = classObj.getDeclaredMethod("isReloadMethod", Integer.class);
System.out.println("Integer.class(not exits):"+method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
执行结果:
getConstructors():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Constructor[] constructors = classObj.getConstructors();
Arrays.stream(constructors).forEach(System.out::println);
}
执行结果:
getConstructor(Class<T>... parameterTypes):
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Constructor constructor;
// getConstructor(Class<T>... parameterTypes)方法会获取符合指定参数列表的public修饰的构造方法
try {
constructor = classObj.getConstructor();
System.out.println("no args(default):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = classObj.getConstructor(String.class);
System.out.println("String.class(public):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = classObj.getConstructor(String.class, String.class);
System.out.println("String.class, String.class(private):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
// 因为本身ReflectTest类就不具备参数列表为只接受一个Integer类型的构造函数,所以会报出没有目标方法的异常
constructor = classObj.getConstructor(Integer.class);
System.out.println("Integer.class(not exits):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
执行结果:
getDeclaredConstructors():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Constructor[] constructors = classObj.getDeclaredConstructors();
Arrays.stream(constructors).forEach(System.out::println);
}
执行结果:
getDeclaredConstructor(Class<T>... parameterTypes):
public static void main(String[] args) {
Class classObj = ReflectTest.class;
Constructor constructor;
// getDeclaredConstructor(Class<T>... parameterTypes)方法会获取符合指定参数列表的构造方法
try {
constructor = classObj.getDeclaredConstructor();
System.out.println("no args(default):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = classObj.getDeclaredConstructor(String.class);
System.out.println("String.class(public):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = classObj.getDeclaredConstructor(String.class, String.class);
System.out.println("String.class, String.class(private):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
constructor = classObj.getDeclaredConstructor(Integer.class);
System.out.println("Integer.class(not exits):" + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
执行结果:
newInstance():
public static void main(String[] args) {
Class classObj = ReflectTest.class;
// newInstance()方法会通过该类的无参构造函数进行对象实例化
try {
Object reflectTest = classObj.newInstance();
System.out.println(reflectTest);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
执行结果: