JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Java反射中常用方法有19个,下面介绍这些方法。
获取Class类对象, 有三种方式:
1. Class Class.forName(“完整的包名.类名”);(最常用)
例如: sueyun.cn.reflect.Person
2. Class 类名.class
3. Class 类对象.getClass();
//首先创建 一个实体类用于演示反射的用法
public class Person {
// 成员变量 Field
private Integer id;
private String name;
public int test = 20;
public static int testStatic = 30;
public Person() {
}
public Person(Integer id) {
super();
this.id = id;
}
public Person(String name) {
super();
this.name = name;
}
public Person(Integer id, String name, int test) {
super();
this.id = id;
this.name = name;
this.test = test;
}
private Person(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private void testPrivate() {
System.out.println("私有化成员方法");
}
public static void testStaticMethod() {
System.out.println("静态成员方法");
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", test=" + test + "]";
}
public void game() {
System.out.println("pubg");
}
public void game(String name) {
System.out.println(this.getName() + "玩" + name);
}
}
下面通过反射方法获取Person类的Class类对象
public class GetClassObject {
public static void main(String[] args) throws ClassNotFoundException {
// Class.forName("完整的包名.类名");
/*
* 最常用!!!
*/
Class cls1 = Class.forName("sueyun.cn.reflact.Person");
// 类名.class
Class cls2 = Person.class;
// 类对象.getClass();
Class cls3 = new Person().getClass();
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls1 == cls2);
System.out.println(cls2 == cls3);
System.out.println(cls3 == cls1);
}
}
首先获取Class类对象,然后通过Class类对象获取该类的构造器。常用方法有:
Constructor getConstructor(Class… parameterTypes);
根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法 Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则报NoSuchMethodException异常根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法
Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则报NoSuchMethodException异常
Constructor[] getConstructors(); 获取当前类内的所有非私有化构造方法
Constructor getDeclaredConstructor(Class… parameterTypes); 根据参数类型,获取指定参数类型的构造方法,可以获取私有化的构造方法
Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制
Constructor[] getDeclaredConstructors(); 获取当前类内的所有构造方法,包括私有化构造方法
Object newInstance(Object… args); 通过Constructor类对象,调用newInstance方法,创建类对象 Object… 不定长参数,用于传入构造方法所需的参数
setAccessible(boolean) ; 给予私有化构造方法,成员方法,成员变量操作权限
代码中有方法如何使用的详细注释:
/**
* 通过Class类对象,来获取Constructor类对象
*
*/
public class GetConstructorObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 首先获取Class类对象
Class cls = Class.forName("sueyun.cn.reflact.Person");
/*
* Constructor[] getConstructors(); 获取当前类内的所有非私有化构造方法
*/
Constructor[] allCons = cls.getConstructors();
for (Constructor constructor : allCons) {
System.out.println(constructor);
}
/*
* 暴力反射 Constructor[] getDeclaredConstructors(); 获取当前类内的所有构造方法,包括私有化构造方法
*/
Constructor[] allC = cls.getDeclaredConstructors();
for (Constructor constructor : allC) {
System.out.println(constructor);
}
/*
* Constructor getConstructor(Class... parameterTypes);
* 根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法 Class类型 ...
* 不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则
* NoSuchMethodException
*/
Constructor nullParamCon = cls.getConstructor(null);
Constructor tParamCon = cls.getConstructor(Integer.class, String.class, int.class);
// cls.getConstructor(Integer.class, String.class);
System.out.println(nullParamCon);
System.out.println(tParamCon);
/*
* 暴力反射 Constructor getDeclaredConstructor(Class... parameterTypes);
* 根据参数类型,获取指定参数类型的构造方法,可以获取私有化的构造方法 Class类型 ...
* 不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制
*/
Constructor privateCon = cls.getDeclaredConstructor(Integer.class, String.class);
System.out.println(privateCon);
/*
* Object newInstance(Object... initargs);
* 通过Constructor类对象,调用newInstance方法,创建类对象 Object... 不定长参数,用于传入构造方法所需的参数
*/
Person p1 = (Person) nullParamCon.newInstance(null);
p1.setId(1);
p1.setName("张三");
System.out.println(p1);
Person p2 = (Person) tParamCon.newInstance(1, "他很帅", 10);
System.out.println(p2);
/*
* setAccessible(boolean) 给予私有化构造方法,成员方法,成员变量操作权限
*/
privateCon.setAccessible(true);
Person p3 = (Person) privateCon.newInstance(2, "演示");
System.out.println(p3);
}
}
public class GetFieldObject {
public static void main(String[] args)
throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Class cls = Class.forName("sueyun.cn.reflact.Person");
/*
* Field[] getFields(); 获取类内的所有非私有化成员变量
*/
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println();
/*
* Field[] getDeclaredFields(); 获取类内的所有成员变量,包括私有化成员变量
*/
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
/*
* Field getField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,只能获取非私有化成员变量
*/
Field test = cls.getField("test");
System.out.println(test);
System.out.println();
/*
* Field getDeclaredField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,可以获取私有化成员变量
*/
Field id = cls.getDeclaredField("id");
Field name = cls.getDeclaredField("name");
System.out.println(id);
System.out.println(name);
/*
* set(Object obj, Object value); Obj: 执行或者说调用当前成员变量的类对象 value: 给成员变量赋值
*/
Person p = (Person) cls.getConstructor(null).newInstance(null);
test.set(p, 100);
System.out.println(p.test);
id.setAccessible(true);
name.setAccessible(true);
id.set(p, 1);
name.set(p, "12345678");
System.out.println(p);
Field testStatic = cls.getField("testStatic");
testStatic.set(null, 10);
System.out.println(p.testStatic);
}
}
public class GetMethodObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Class cls = Class.forName("sueyun.cn.reflact");
/*
* Method[] getMethods(); 获取类内非私有化成员方法,和从父类继承而来的可以在子类使用的成员方法
*/
Method[] allMethods = cls.getMethods();
for (Method method : allMethods) {
System.out.println(method);
}
System.out.println();
/*
* Method[] getDeclaredMethods(); 获取当前类的所有成员方法,包括私有化成员方法,但是不包含从父类继承而来的方法
*/
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println();
/*
* Method getMethod(String methodName, Class... parameterTypes);
* 根据方法名和参数类型,获取指定的非私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
*/
Method gameMethos1 = cls.getMethod("game", null);
Method gameMethos2 = cls.getMethod("game", String.class);
System.out.println(gameMethos1);
System.out.println(gameMethos2);
/*
* Method getDeclaredMethod(String methodName, Class.. parameterTypes);
* 根据方法名和参数类型,可以获取指定的私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
*/
Method privateMethod = cls.getDeclaredMethod("testPrivate", null);
System.out.println(privateMethod);
System.out.println();
/*
* invoke(Object obj, Object... args); 指定Method类对象方法 obj: 执行当前方法的类对象 args:
* 不定长参数,是当前执行方法所需的实际参数列表
*
* cls.getConstructor(null).newInstance(null) 通过反射获取构造方法,并且创建对象
*/
gameMethos1.invoke(cls.getConstructor(null).newInstance(null), null);
gameMethos2.invoke(cls.getConstructor(Integer.class, String.class, int.class).newInstance(1, "反射没有那么难", 20),
"张三");
privateMethod.setAccessible(true);
privateMethod.invoke(cls.getConstructor(null).newInstance(null), null);
// 执行类内的静态成员方法,invoke第一个参数可以是null
cls.getMethod("testStaticMethod", null).invoke(null, null);
}
}