反射
- 反射之框架的灵魂。
- JAVA反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射。
- 实质:反射就是加载类,并解析出类的各个部分。
相关概念
框架: 1)就是一些接口和类的集合,通过这些接口和类协调来完成一些列的功能。
2)框架是一个软件半成品,它的出现让我们把主要精力集中于业务逻辑。
反射的好处
1.代码解耦
2.程序运行中操作对象
Java代码的三个阶段
Source(源码)阶段,此时还在硬盘中
Class(类对象)阶段,此时有类加载器把.class文件加载到内存中,生成类对象
RunTime(运行时)阶段,此时也在内存中,可以执行对象的方法和访问对象的任意成员变量
类的加载
- Class,forName(“全类名”)、
- 类名.class;
- 对象.getClass();
package com.fubo;
public class Demo2 {
public static void main(String[] args) {
//加载类
try {
//1.方式1
Class<?> aClass = Class.forName("com.fubo.Demo1");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//1.方式2
Class<Demo1> demo1Class = Demo1.class;
//1.方式1
Demo1 demo1 = new Demo1();
Class<? extends Demo1> aClass = demo1.getClass();
System.out.println(aClass);
}
}
解析类的各个部分(这个是类对象的功能)
解析成员变量
- Field[] getFields() // 返回一个包含某些
Field
对象的数组,这些对象反映此Class
对象所表示的类或接口的所有可访问公共字段。- Field[] getDeclaredFileds() //返回
Field
对象的一个数组,这些对象反映此Class
对象所表示的类或接口所声明的所有字段。- Field getField(String name) // 返回一个
Field
对象,它反映此Class
对象所表示的类或接口的指定公共成员字段。- Field getDeclaredField(String name) //返回
Field
对象的一个数组,这些对象反映此Class
对象所表示的类或接口所声明的所有字段。
Field类
封装成员变量的类
常用的方法:
设置成员变量的值
void set(Object obj, Object value)
// 将指定对象(obj)变量上此 `Field` 对象表示的字段设置为指定的新值。
获取成员变量的值。
Object get(Object obj)
//返回指定对象上此 `Field` 表示的字段的值。
3.忽略访问权限符的限制
void **setAccessible**(boolean flag) //将此对象的 `accessible` 标志设置为指示的布尔值。
获取字段类型
Class<?> getType()
//返回一个
Class
对象,它标识了此Field
对象所表示字段的声明类型。
package com.fubo;
import com.fubo.com.fubo.entity.Student;
import java.lang.reflect.Field;
public class Demo3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//1.加载类对象
Class<Student> studentClass = Student.class;
//2.解析成员变量
Field[] fields = studentClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Student stu = new Student();
stu.setUsername("zs");
Field[] declaredFields = studentClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName()+","+declaredField.getType());
}
Field realname = studentClass.getField("realname");
//给stu这个变量的realname字段赋值
realname.set(stu,"好汉");
System.out.println(realname.get(stu));
Field username = studentClass.getDeclaredField("username");
//暴力访问,我们可以操作所有字段
username.setAccessible(true);
username.set(stu,"hh");
System.out.println(username.get(stu));
}
}
解析构造方法
- Constructor[] getConstructors()//返回一个包含某些
Constructor
对象的数组,这些对象反映此Class
对象所表示的类的所有公共构造方法。- Constructor[]getDeclaredConstructors()// 返回
Constructor
对象的一个数组,这些对象反映此Class
对象表示的类声明的所有构造方法。- ConstructorgetConstructor(Class<?>… parameterTypes) // 返回一个
Constructor
对象,它反映此Class
对象所表示的类的指定公共构造方法。- ConstructorgetDeclaredConstructor(Class<?>… parameterTypes)//返回一个
Constructor
对象,该对象反映此Class
对象所表示的类或接口的指定构造方法
Constructor类
封装构造器的类。
常用方法:
通过构造器创建对象
T newInstance(Object… initargs)
//使用此
Constructor
对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。注:如果是无参构造器,一般不使用此种方法,使用类对象.newInstance()
忽略访问权限符的限制
void setAccessible(boolean flag)
//将此对象的
accessible
标志设置为指示的布尔值。
package com.fubo;
import com.fubo.com.fubo.entity.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo4 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//1.加载类对象
Class<Student> studentClass = Student.class;
//2.解析构造器
Constructor<?>[] constructors = studentClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.toString());
}
Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.toString());
}
Constructor<Student> constructor = studentClass.getConstructor();
System.out.println(constructor.toString());
Constructor<Student> constructor2 = studentClass.getConstructor(String.class,String.class,Integer.class,String.class);
System.out.println(constructor2.toString());
Constructor<Student> constructor3 = studentClass.getDeclaredConstructor(String.class);
System.out.println(constructor3.toString());
constructor3.setAccessible(true);
Student lisi = constructor3.newInstance("lisi");
System.out.println(lisi.getUsername());
//通过无参构造去创建对象时,推荐使用如下方法,类对象.newInstance();
Student student = studentClass.newInstance();
}
}
解析成员方法
- Method[] getMethods() //返回一个包含某些
Method
对象的数组,这些对象反映此Class
对象所表示的类或接口的公共方法(包含父类的公共方法)- Method[]getDeclaredMethods()// 返回
Method
对象的一个数组,这些对象反映此Class
对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。- Method getMethod(String name, Class<?>… parameterTypes)// 返回一个
Method
对象,它反映此Class
对象所表示的类或接口的指定公共成员方法。- Method getDeclaredMethod(String name, Class<?>… parameterTypes)// 返回一个
Method
对象,该对象反映此Class
对象所表示的类或接口的指定已声明方法。
Method类
成员方法的封装类
常用方法:
Object invoke(Object obj, Object… args)
// 对带有指定参数的指定对象调用由 此
Method
对象表示的底层方法。忽略访问权限符的限制
void setAccessible(boolean flag)
//将此对象的
accessible
标志设置为指示的布尔值获取Method类封装的方法的名称
String getName()
// 以
String
形式返回此Method
对象表示的方法名称。
package com.fubo;
import com.fubo.com.fubo.entity.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
public class Demo5 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//1.加载类对象
Class<Student> studentClass = Student.class;
//2.解析成员方法
Method[] methods = studentClass.getMethods();
/* for (Method method : methods) {
System.out.println(method.toString());
}*/
Method[] declaredMethods = studentClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
Student student = studentClass.newInstance();
Method say = studentClass.getMethod("say");
say.invoke(student);
Method say2 = studentClass.getMethod("say",String.class);
say2.invoke(student,"我什么也不想说");
Method say3 = studentClass.getDeclaredMethod("say",String.class, Date.class);
say3.setAccessible(true);
say3.invoke(student,"我什么也不想说",new Date());
}
}