文章目录
反射
允许对成员变量\成员方法\构造方法的信息进行编程访问
把类内的信息扒的干干净净,获取+解剖
获取从class字节码文件中获取
获取class对象的三种方式
public static void main(String[] args) throws ClassNotFoundException {
//第一种
//最为常用
Class<?> aClass = Class.forName("com.itheima.stream.Student");
System.out.println(aClass);
//第二种
//更多是作为参数进行传递
Class<Student> studentClass = Student.class;
System.out.println(studentClass);
//第三种
//有了这个类的对象,才可以使用
Student student = new Student();
Class<? extends Student> aClass1 = student.getClass();
System.out.println(aClass1);
}
获取构造方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getConstructors();//返回所有的公共构造方法
// aClass.getDeclaredConstructors();//返回所有的构造方法
// aClass.getConstructor();//返回单个公共的构造方法
// aClass.getDeclaredConstructor();//返回单个的构造方法
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
//获取构造中的参数
Parameter[] parameters = declaredConstructor.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//用反射创建对象
//如果是私有的构造方法,需要设置 accessible 为 true,暴力反射访问
declaredConstructor.setAccessible(true);
Student student = (Student) declaredConstructor.newInstance("张三", 23);
System.out.println(student);
}
获取成员变量
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getFields();
// aClass.getDeclaredFields();
// aClass.getField();
// aClass.getDeclaredField();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Field name = aClass.getField("name");
//获取权限修饰符
System.out.println(name.getModifiers());
//获取成员变量类型
System.out.println(name.getType());
}
获取成员方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getMethods();//获取所有的方法(包含父类)
// aClass.getDeclaredMethods();//获取本类所有的方法(不包含父类)
Method method = aClass.getMethod("toString");
// aClass.getDeclaredMethod();
//获取抛出的异常
Class<?>[] exceptionTypes = method.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType.getName());
}
Method eat = aClass.getMethod("eat", String.class);
Student student = new Student();
Object out = eat.invoke(student, "汉堡");
System.out.println(out);
}
这里的invoke是重点,苍穹外卖的代理有用到
反射的作用
-
获取一个类里面所有的信息,获取到之后,再执行其他的业务逻辑
-
结合配置文件,动态的创建对象并调用方法
确实,我也想不出来怎么从配置文件中获取或修改方法类public static void saveObject(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = object.getClass();
//获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
String name = declaredField.getName();
Object o = declaredField.get(object);
System.out.println(name + ":" + o);
}
}
动态代理
无侵入式的给对象增强其他的功能
代理工具类
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),//指定用哪个类加载器,去加载生成的代理
new Class[]{Star.class},//指定代理类需要实现的接口
new InvocationHandler() {//指定生成的代理要干什么
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//参数1,代理对象
//参数2,要调用的方法
//参数3,调用方法时,传递的参数
if ("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
} else if ("dance".equals(method.getName())) {
System.out.println("准备场地,收钱");
}
return method.invoke(bigStar,args);
}
});
return star;
}
代理对象
public class BigStar implements Star{
private String name;
public BigStar() {
}
public BigStar(String name) {
this.name = name;
}
@Override
public String sing(String name){
System.out.println(this.name+"正在唱歌"+name);
return "谢谢";
}
@Override
public void dance(){
System.out.println(this.name+"正在跳舞");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
public String toString() {
return "BigStar{name = " + name + "}";
}
}
代理对象对应准备的接口,用接口代理对象实现附加功能
public interface Star {
void dance();
String sing(String name);
}
测试
public static void main(String[] args) {
Star proxy = ProxyUtil.createProxy(new BigStar("王宝强"));
String result = proxy.sing("某某");
System.out.println(result);
}