文章目录
- 反射
- 获取class对象的三种方式
- 获取构造方法
- 获取成员变量
- 获取成员方法
- 反射的作用
- 动态代理
反射
允许对成员变量\成员方法\构造方法的信息进行编程访问
把类内的信息扒的干干净净,获取+解剖
获取从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() {//指定生成的代理要干什么@Overridepublic 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;}@Overridepublic String sing(String name){System.out.println(this.name+"正在唱歌"+name);return "谢谢";}@Overridepublic 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);
}