1、反射相关的主要类
-
java.lang.Class<T>
:Class对象表示某个类加载后在堆中的对象(获取字节码对象),通过获取到的对象然后可以获得类的其他属性。
①:public Field getField(String name)
:获取属性对象。
②:public Constructor<T> getConstructor(Class<?>... parameterTypes)
:获取构造方法对象。
③:public Method getMethod(String name, Class<?>... parameterTypes)
: 获取指定方法对象。 -
java.lang.reflect.Field
:代表类的成员变量,Filed对象表示某个类的成员变量。
①:Field
表示一个类中的属性,每一个属性,都是该类的一个实例。
②:public void set(Object obj, Object value)
:给指定对象obj
设置值value
。
③:public Object get(Object obj)
:获取指定对象obj中存储的属性的值。 -
java.lang.reflect.Constructor<T>
:代表类的构造方法,Constructor对象表示构造器,泛型表示对应的实例对象类型。
①:public T newInstance(Object ... initargs)
:根据获取的构造器对象创建实例。 -
java.lang.reflect.Method
:代表类的方法,Method对象表示某个方法类的方法。
①:Object invoke(Object obj, Object... args)
:obj
表示要执行的方法是哪个对象的;args
表示执行方法时所需要的实际参数,没有参数时可不写;object
表示方法返回值(没有时不写)。
简单的例子:
public class ReflectionQuestion {
public static void main(String[] args) throws Exception {
// 根据配置文件 re.properties指定的信息,创建Cat实例
Properties properties = new Properties();
properties.load(new FileInputStream("reflection\\src\\re.properties"));
String clssfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
//-----使用反射创建对象
// 1. 加载类,得到Class类型的对象
Class cls = Class.forName(clssfullpath);
// 2. 通过加载类,得到Cat实例
Object o = cls.newInstance();
System.out.println(o.getClass());
// 3.把这个方法当做一个对象,得到后返回
Method method = cls.getMethod(methodName);
System.out.println("===========");
// 4.通过method调用方法:即通过方法的对象来调用方法
method.invoke(o); //传统调用方法 对象.方法() , 反射机制调用方法:方法.invoke(对象)
// 通过反射调用Cat对象的cry方法
Method cry = cls.getMethod("cry"); //这个cry可以从配置文件中获取,达到修改配置文件调用方法
cry.invoke(o);
}
}
re.properties
classfullpath=com.Cat
method=hi
Cat类
public class Cat {
private String name = "招财猫";
public int age = 10;
//setter()和getter()
}
2、反射构造方法创建实例
public Constructor<T> getConstructor(Class<?>... parameterTypes)
:获取构造器对象。public T newInstance(Object ... initargs)
:根据获取的构造器对象创建实例。
/**
* 反射
* 一个类型的字节码(.class)文件进入内存一次,字节码文件在内存中对应的class对象只有一个
* 使用构造方法创建对象
*/
public static void main(String[] args) throws Exception {
Class<?> cls1 = Class.forName("com.day25.Student");
Class<?> cls2 = Class.forName("com.day25.Student");
System.out.println(cls1 == cls2); //返回为true
Constructor<?>[] cs = cls1.getConstructors(); //获取所有public构造方法
for (Constructor<?> c : cs) {
System.out.println(c);
}
Constructor<?> c = cls1.getConstructor(String.class, int.class); //获取指定的构造方法,这里的参数是构造方法中参数的类型
Object o = c.newInstance("张三", 9); //如果获取的构造方法需要参数,这里就需要按顺序写入参数
System.out.println(o);
}
class Student {
private String name;
private int age;
public Student() {
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//setter()和getter()
//toString()
}
3、反射获取方法
public Method[] getMethods()
:获取一个类中的所有的public修饰的成员方法,返回值是一个Method类型的数组。public Method getMethod(String name, Class<?>... parameterTypes)
: 获取指定方法对象
①:name
:表示方法名
②:parameterTypes
:一个可变参数,表示方法参数的类型- Method类:
①:Object invoke(Object obj, Object... args)
:obj
表示要执行的方法是哪个对象的;args
表示执行方法时所需要的实际参数;object
表示方法返回值。
代码:
public class Demo3 {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("com.day25.Person");
Object o = cls.newInstance();
Method eat = cls.getMethod("eat", String.class); // 没有参数可以不写类型
eat.invoke(o,"满汉全席"); // 没有参数可以不写
}
}
person类:
public class Person {
public String name;
public int age;
public String sex;
public Person() {
}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void eat(String name){
System.out.println("吃" + name);
}
}
输出:
吃满汉全席
4、反射获取属性
public Field getField(String name)
:获取Field
对象Field
类型:
①:Field
表示一个类中的属性,每一个属性,都是该类的一个实例
②:public void set(Object obj, Object value)
:给指定对象obj设置值value
③:public Object get(Object obj)
:获取指定对象obj中存储的属性的值
/**
* 反射获取属性
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.day25.Person");
Field[] fields = cls.getFields(); //获取所有公共的属性
for (Field field : fields) {
System.out.println(field);
}
System.out.println("========");
//获取指定属性
Field name = cls.getField("name");
System.out.println(name);
//根据获取的属性修改属性值
Object o = cls.newInstance(); //先获取指定的对象
name.set(o, "张三");
System.out.println(name.get(o));
}
}
5、暴力反射
Class
对象获取私有属性:有一些getDeclared*****
开头的方法,这些方法可以获取到类中的,所有的构造方法,所有的属性,所有的方法,不管是public还是private修饰的都可以获取到。AccessibleObject
类:Field
、Constructor
、Method
类都是这个类的子类。这个类有个能力,可以使该类或者其子类能够忽略调用权限检测符的能力
①:public void setAccessible(boolean flag)
:将参数设置为true,就不会再检测这个对象权限修饰符,直接能够使用,如果设置false,就会检测权限修饰符。
②:public boolean isAccessible()
:返回一个对象是否有设置取消权限检测。
例:
public class Demo6 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.day25.Student");
Constructor<?> con = cls.getDeclaredConstructor(String.class, int.class); // 获取私有的构造方法
con.setAccessible(true); //取消权限检测
Object o = con.newInstance("张三", 99);
System.out.println(o);
}
}
class Student {
private String name;
private int age;
private Student() {
}
private Student(int age) {
this.age = age;
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出:
Student{name=‘张三’, age=99}