前言
本文介绍了创建反射的三种方式,主要了解如何通过反射获取对象中的构造器、成员变量和成员方法。
一、反射是什么?
反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。
二、获取反射的三种方式
直接使用类名.class获取:Class c1 = 类名.class
调用Class提供的方法:Class c2 = Class.forName(“全类名”)
调用Object提供的方法:Class c3 = 对象.getClass()
代码如下:
/*
反射的第一步是什么
获取Class类对象,如此才可以解析类的全部成分
获取Class对象的三种方式
1. 直接使用类名.class获取:Class c1 = 类名.class
2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
3. 调用Object提供的方法:Class c3 = 对象.getClass()
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
Class<Cat> catClass = Cat.class;
Class<?> aClass = Class.forName("com.itheima.b_反射.Cat");
Class<? extends Cat> aClass1 = new Cat().getClass();
}
}
三、获取类的构造器
获取构造器[下面是Class的方法]
Constructor<?>[] getConstructors() 获取所有的公共构造器(只能获取public修饰的) Constructor<?>[] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)
Constructor getConstructor(Class<?>... parameterTypes) 获取某个公共构造器(只能获取public修饰的) Constructor getDeclaredConstructor(Class<?>… parameterTypes) 获取某个构造器(只要存在就能拿到)
使用构造器(创建对象)[下面是Constructor的方法]
T newInstance(Object… initArgs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
注意
使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
代码如下:
public class Cat {
public static int a;
public static final String COUNTRY = "中国";
private String name;
private int age;
public Cat(){
System.out.println("无参数构造器执行了~~");
}
public Cat(String name){
System.out.println("无参数构造器执行了~~");
this.name = name;
}
private Cat(String name, int age) {
System.out.println("有参数构造器执行了~~");
this.name = name;
this.age = age;
}
private void run(){
System.out.println("🐱跑的贼快~~");
}
public void eat(){
System.out.println("🐱爱吃猫粮~");
}
private String eat(String name){
return "🐱最爱吃:" + name;
}
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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo2 {
public static void main(String[] args) throws Exception {
Class<Cat> catClass = Cat.class;
System.out.println(catClass.getName());
Constructor[] constructors = catClass.getConstructors();
for (Constructor constructor:constructors) {
System.out.println(constructor);
}
System.out.println("------------------");
Constructor<?>[] declaredConstructors = catClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("------------------");
Constructor<Cat> constructor = catClass.getConstructor();
System.out.println(constructor);
System.out.println("------------------");
Constructor<Cat> constructor1 = catClass.getConstructor(String.class);
Cat cat = constructor1.newInstance("猫");
System.out.println(cat);
Constructor<Cat> declaredConstructor = catClass.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
System.out.println(declaredConstructor.newInstance("小猫", 23));
}
}
四、获取类的成员变量
获取成员变量[Class提供]
public Field[] getFields() 获取类的所有公共成员变量(只能获取public修饰的)
public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
public Field getField(String name) 获取类的某个公共成员变量(只能获取public修饰的)
public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)
使用成员变量(赋值和取值) [Field提供]
public void set(Object obj, Object value): 赋值
public Object get(Object obj): 取值
public void setAccessible(boolean flag): 设置为true,表示禁止检查访问控制(暴力反射)
注意
使如果想使用private修饰的变量,需要暴力反射
public class Demo3 {
public static void main(String[] args) throws Exception {
Cat cat = new Cat();
Class<? extends Cat> aClass = cat.getClass();
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
Object o = field.get(cat);
System.out.println(o);
}
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
System.out.println(declaredField.get(cat));
}
System.out.println(aClass.getField("COUNTRY").get(cat));
Field names = aClass.getDeclaredField("name");
names.setAccessible(true);
System.out.println(names.get(cat));
}
}
五、获取类的成员方法
获取成员方法[Class提供]
Method[] getMethods() 获取类的全部公共成员方法(只能获取public修饰的)
Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)
Method getMethod(String name, Class<?>... parameterTypes) 获取类的某个公共成员方法(只能获取public修饰的) Method getDeclaredMethod(String name, Class<?>… parameterTypes) 获取类的某个成员方法(只要存在就能拿到)
使用成员方法(执行方法)[Method提供]
public Object invoke(Object obj, Object… args) 触发某个对象的该方法执行。
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
注意
使如果想使用private修饰的成员方法,需要暴力反射
public class Demo4 {
public static void main(String[] args) throws Exception {
Class catClass = Cat.class;
Method[] methods = catClass.getMethods();
for (Method method : methods) {
System.out.println(method.getName() +"--------"+ method.getReturnType()+"--------" + method.getParameterCount());
}
Method[] declaredMethods = catClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method.getName() +"--------"+ method.getReturnType()+"--------" + method.getParameterCount());
}
Method eat = catClass.getMethod("eat");
Method eat1 = catClass.getDeclaredMethod("eat", String.class);
Cat cat = new Cat();
System.out.println(eat.invoke(cat));
eat1.setAccessible(true);
Object invoke = eat1.invoke(cat,"肉");
System.out.println(invoke);
}
}
总结
三种创建反射的方式熟练掌握,学会拿到对象的构造器、成员变量和成员方法,拿到这三个的方式差不多,方法不一样但都有规律,很容易记住。