Java——反射
Java虽然不是动态语言,但有和动态机制相关的重要概念——反射。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射的源头是Class类。一个类在加载到内存中后,就会存在代表当前类的唯一的Class对象,这个Class对象中保存了加载到内存中的这个类的所有信息。
获取Class对象
获取Class对象的方式有三种:
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
//1、类名.class
Class strClass1 = String.class;
//2、对象.getClass()
Class strClass2 = (new String()).getClass();
//3、Class的静态方法forName("类的全限定名")
Class strClass3 = Class.forName("java.lang.String");
}
}
获取修饰符
取得Class对象我们就可以获取它表示类的修饰符,返回整型变量。
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
Class strClass = String.class;
//获取修饰符
int modifiers = strClass.getModifiers();
System.out.println(modifiers);
}
}
获取构造函数
通过下面四个方法可以获得构造函数。
方法 | 用处 |
---|---|
Constructor getConstructor(Class<?>… parameterTypes) | 获取一个指定的公共构造器对象 |
Constructor<?>[] getConstructors() | 获取所有的公共的构造器对象数组 |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 所有权限的构造器的指定一个 |
Constructor<?>[] getDeclaredConstructors() | 获取所有构造器的数组 |
创建一个Person类:
public class Person {
private String name;
private int age;
//公有的空构造
public Person() {}
//默认构造器,传入姓名
Person(String name){
this.name = name;
}
//私有构造,传入姓名和年龄
private Person(String name,int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
调用上面的四个方法获得构造器类对象或构造器类的数组
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取Person类的Class对象
Class personCls = Class.forName("reflect.Person");
//1、获取一个指定的公有构造器
Constructor con1 = personCls.getConstructor();
//2、获取公有构造器的数组
Constructor[] cons1 = personCls.getConstructors();
//3、获取一个指定的构造器,传入参数类型的Class对象
Constructor con2 = personCls.getDeclaredConstructor(String.class,int.class);
//4、获取所有构造器的数组
Constructor[] cons2 = personCls.getDeclaredConstructors();
}
}
通过构造函数类的对象我们可以获取反射类的对象。也可以通过Class对象直接调用newInstance()方法,使用空构造器返回一个对象,但若是没有空构造会报java.lang.NoSuchMethodException异常。因此推荐使用构造器类的成员方法newInstance()来获取对象。
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
//获取Person类的Class对象
Class personCls = Class.forName("reflect.Person");
//获取一个指定的构造器
Constructor con = personCls.getDeclaredConstructor(String.class,int.class);
//设置没有权限的构造器为可操作
con.setAccessible(true);
//创建Person类对象
Person person = (Person) con.newInstance("慕",18);
System.out.println(person);
//关闭权限
con.setAccessible(false);
}
}
获取方法
方法 | 用处 |
---|---|
Method getMethod(String name, Class<?>… parameterTypes) | 根据方法名和参数类型的Class对象,获取一个指定的公共方法 |
Method[] getMethods() | 获取所有的公共方法数组,包括继承的 |
Method getDeclaredMehod(String name, Class<?>… parameterTypes) | 根据方法名和参数类型的Class对象,获取所有权限的方法的指定一个 |
Method[] getDeclaredMethods() | 获取所有方法的数组 |
Person类中创建一些方法:
public class Person {
private String name;
private int age;
//属性的set、get方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//成员方法
private String show() {
return "我叫"+name+",今年"+age+"岁了。";
}
//静态方法
public static void sleep(int i) {
System.out.println("每天睡"+i+"个小时");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
Class<Person> pCls = Person.class;
Person p = pCls.newInstance();
//1、获取指定公有方法
Method m1 = pCls.getMethod("getName");
//2、获取公有方法的数组,只有这个方法获取继承的公有方法
Method[] methods = pCls.getMethods();
for(Method m:methods) {
System.out.println(m);
}
//3、获取所有权限方法的指定一个,没有权限的要打开权限
Method m2 = pCls.getDeclaredMethod("show");
//普通方法调用,invoke(对象,参数)
m2.setAccessible(true);
System.out.println(m2.invoke(p));
m2.setAccessible(false);
//4、获取所有方法的数组
Method[] methods2 = pCls.getDeclaredMethods();
for(Method m:methods2) {
System.out.println(m);
}
//静态方法调用
methods2[3].invoke(null, 8);
}
}
获取属性
方法 用处 Field getField(String name) 返回一个 Field指定对象,代表了公共成员属性 Field[] getFields() 返回代表公有属性的数组 Field getDeclaredField(String name) 返回一个 Field指定对象,代表了所有权限的成员属性 Field[] getDeclaredFields() 返回代表所有权限属性的数组 获取方法Method对象后,可以用void set(Object obj, Object value)设置值,用 get(Object obj) 获取值。
public class ReflectDemo5 {
public static void main(String[] args) throws Exception {
Class<Person> pCls = Person.class;
Person p = pCls.newInstance();
Field field1 = pCls.getDeclaredField("name");
Field field2 = pCls.getDeclaredField("age");
field1.setAccessible(true);
field2.setAccessible(true);
field1.set(p, "尾巴");
field2.set(p,18);
System.out.println("我叫"+field1.get(p)+",今年"+field2.get(p)+"岁了");
field1.setAccessible(false);
field2.setAccessible(false);
}
}