Java_反射(Class文件对象 / 反射 / 动态代理)
2017-08-23 20:17
603 查看
Java_反射(Class文件对象 / 反射 / 动态代理)
本文由 Luzhuo 编写,转发请保留该信息.原文:
http://blog.csdn.net/Rozol/article/details/77511333
反射: 在运行状态时, 能够获取任意一个类的所有属性和方法; 能够调用任意一个对象的所有属性和方法.
反射性能较低, 一般情况下不考虑用反射.
Proxy 动态代理: 用来修改已经具有的对象的方法, 控制方法是否执行, 或在方法执行之前和执行之后做一些额外的操作
Bean类
public class Bean { /** * 公有属性 */ public int number = 10; /** * 私有属性 */ private String name = Bean.class.getSimpleName(); /** * 静态属性 */ public static int max = Integer.MAX_VALUE; /** * 常量属性 */ protected static final int min = Integer.MIN_VALUE; /** * 无参构造 */ public Bean(){} /** * 有参构造 * @param numbder */ public Bean(int number){ this.number = number; } /** * 私有构造 * @param number * @param name */ private Bean(int number, String name){ this.number = number; this.name = name; } protected Bean(int number, String name, int max){ this.number = number; this.name = name; Bean.max = max; } /** * 公有方法 * @param number */ public void setNumber(int number){ this.number = number; } public int getNumber(){ return this.number; } /** * 私有方法 */ private void setName(String name){ this.name = name; } private String getName(){ return this.name; } /** * 静态方法 * @param max */ public static void setMax(int max){ Bean.max = max; } public static int getMax(){ return Bean.max; } /** * protected方法 * @param min * @return */ protected int getMin(){ return Bean.min; } @Override public String toString() { return "Bean [number=" + number + ", name=" + name + ", max=" + Bean.max + ", min =" + Bean.min + "]"; } }
@Deprecated public class SubBean extends Bean implements Serializable{ /** * 调用父类方法, 并抛出一个异常 * @return * @throws Exception */ public int getSuperNumber(int number) throws Exception{ return super.getNumber(); } }
Class文件对象
在使用反射之前, 首先要获取Class类的文件对象, 然后才能通过反射去获取类的方法, 之后才能调用该方法./** * 获取Class文件对象的几种方式 * @author Luzhuo */ public class GetClass { public static void main(String[] args) throws ClassNotFoundException { // 方式1: 通过对象获得 GetClass getClass = new GetClass(); Class<? extends GetClass> class1 = getClass.getClass(); // 方式2: 通过数据类型的一个静态calss属性 Class<GetClass> class2 = GetClass.class; // 方式3: 通过全类名获得 Class<?> class3 = Class.forName("反射.reflect.GetClass"); // 方式4: 通过 类加载器 加载 Class<?> class4 = GetClass.class.getClassLoader().loadClass("反射.reflect.GetClass"); System.out.println(class1 == class2 && class2 == class3 && class3 == class4); // true } }
反射
反射: 在运行状态时, 能够获取任意一个类的所有属性和方法; 能够调用任意一个对象的所有属性和方法./** * 反射: 在运行状态时, 能够获取任意一个类的所有属性和方法; * 能够调用任意一个对象的所有属性和方法. * * 反射性能较低, 一般情况下不考虑用反射. * @author Luzhuo */ public class reflect { public static void main(String[] args) throws Exception { // 创建对象(构造方法) constructor(); // 属性 field(); // 方法 method(); // 案例: 通过反射调用已存在对象的方法 callOldInstance(); } /** * 对象的创建(构造方法) * 访问 private / protected 修饰的构造方法时, 需要取消语法检查 */ private static void constructor() throws Exception { // 方式1: Class文件对象 Class<?> clazz = Bean.class; Bean instance1 = (Bean) clazz.newInstance(); // 方式2: Class文件对象的构造方法 Constructor<?>[] cons = clazz.getConstructors(); // 所有公共构造方法 Constructor<?>[] allcons = clazz.getDeclaredConstructors(); // 所有构造方法(public / private / protected) Constructor<?> con = clazz.getConstructor(int.class); // 获取指定公有构造方法 Constructor<?> decCon = clazz.getDeclaredConstructor(int.class, String.class); // 获取指定私有构造方法 decCon.setAccessible(true); // 取消Java语言访问检查(获取 private / protected 构造时使用) Bean instance2 = (Bean) cons[0].newInstance(200); Bean instance3 = (Bean) cons[1].newInstance(); System.out.println(instance1 == instance2 || instance2 == instance3); // false // 访问 private / protected 修饰的构造方法时, 需要取消语法检查 } /** * 属性 * 访问 private / protected / static final 修饰的属性时, 需要取消语法检查 * 修改 private / protected 修饰的属性时, 需要取消语法检查, 不能修改 static final 修饰的属性 * 能获取本类所有字段, 但不能获取父类除public外的所有字段 */ private static void field() throws Exception { Class<?> clazz = Bean.class; // 获取成员变量 Field[] fields = clazz.getFields(); // 所有公共字段(public)(含父类) Field[] allfields = clazz.getDeclaredFields(); // 本类所有字段(public / private / protected) Object obj = clazz.getConstructor().newInstance(); // 创建对象 // 使用成员变量 // 公有属性 Field number = clazz.getField("number"); // 获取指定公有字段(public) System.out.println("number: " + number.getInt(obj)); // 获取字段的值 number.set(obj, 1000); // 设置字段的值 System.out.println(obj.toString()); // 私有属性 Field name = clazz.getDeclaredField("name"); // 获取指定字段(...) name.setAccessible(true); System.out.println("name: " + name.get(obj)); name.set(obj, "set name"); System.out.println(obj.toString()); // 静态属性 Field max = clazz.getField("max"); System.out.println("max: " + max.getInt(obj)); max.set(obj, 123); System.out.println(obj.toString()); // 常量属性(protected) Field min = clazz.getDeclaredField("min"); min.setAccessible(true); System.out.println("min: " + min.getInt(obj)); // min.set(obj, 321); // static final 修饰的属性不允许修改 System.out.println(obj.toString()); // 访问 private / protected / static final 修饰的属性时, 需要取消语法检查 // 修改 private / protected 修饰的属性时, 需要取消语法检查, 不能修改 static final 修饰的属性 // 能获取本类所有字段, 但不能获取父类除public外的所有字段 } /** * 方法 * 能获取该类的所有方法, 但是不能获取父类除public外的所有方法 * 访问 private / protected 修饰的方法时, 需要取消语法检查 */ private static void method() throws Exception{ Class<?> clazz = Bean.class; Method[] allmethods = clazz.getMethods(); // 获取所有公共方法(public / public final / public static)(含父类) Method[] methods = clazz.getDeclaredMethods(); // 获取本类所有方法(public / private / public static / private / protected ...) Object obj = clazz.getConstructor().newInstance(); // 创建对象 // 方法 // 公有 Method setNumber = clazz.getMethod("setNumber", int.class); // 获取指定公共方法(public) setNumber.invoke(obj, 1000); // 调用方法 Method getNumber = clazz.getMethod("getNumber"); int number = (int) getNumber.invoke(obj); System.out.println("getNumber: " + number); // 私有 Method setName = clazz.getDeclaredMethod("setName", String.class); // 获取指定方法(...) setName.setAccessible(true); setName.invoke(obj, "abc"); Method getName = clazz.getDeclaredMethod("getName"); getName.setAccessible(true); String name = (String) getName.invoke(obj); System.out.println("getName: " + name); // 静态 Method setMax = clazz.getMethod("setMax", int.class); setMax.invoke(obj, 123); // 调用方法 Method getMax = clazz.getMethod("getMax"); int max = (int) getMax.invoke(obj); System.out.println("getMax: " + max); // protected Method getMin = clazz.getDeclaredMethod("getMin"); getMin.setAccessible(true); int min = (int) getMin.invoke(obj); System.out.println("getMin: " + min); // 能获取该类的所有方法, 但是不能获取父类除public外的所有方法 // 访问 private / protected 修饰的方法时, 需要取消语法检查 } /** * 通过反射调用已存在对象的方法 */ private static void callOldInstance() throws Exception { Bean bean = new Bean(); Class<? extends Bean> clazz = bean.getClass(); // 通过反射调用私有方法 Method getName = clazz.getDeclaredMethod("getName"); getName.setAccessible(true); String name = (String) getName.invoke(bean); System.out.println("getName: " + name); bean.number = 100000000; // 通过反射调用已存在对象的公有方法 Method getNumber = clazz.getMethod("getNumber"); int number = (int) getNumber.invoke(bean); System.out.println("getNumber: " + number); } }
反射补充
反射相关的一些补充/** * 反射的一些补充 * @author Luzhuo */ public class Other { public static void main(String[] args) throws Exception { Class<?> clazz = SubBean.class; // 包名 String packageName = clazz.getPackage().getName(); System.out.println("包名: " + packageName); // 包名: 反射.Class // 完整类名 String className = clazz.getName(); System.out.println("完整类名: " + className); // 完整类名: 反射.Class.Clazz // 类名 String classSimpleName = clazz.getSimpleName(); System.out.println("类名: " + classSimpleName); // 类名: Clazz // 获取接口 Class<?>[] interfaces = clazz.getInterfaces(); System.out.println("Interfaces: " + Arrays.toString(interfaces)); // 获取父类 Class<?> superClass = clazz.getSuperclass(); System.out.println("SuperClass: " + superClass); // 获取异常 Method getSuperNumber = clazz.getMethod("getSuperNumber", int.class); Class<?>[] exceptions = getSuperNumber.getExceptionTypes(); System.out.println("Exceptions: " + Arrays.toString(exceptions)); // 获取权限修饰符 int mod = getSuperNumber.getModifiers(); System.out.println("Mod: " + Modifier.toString(mod)); // 获取返回值类型 Class<?> returnType = getSuperNumber.getReturnType(); System.out.println("Return Type: " + returnType); // 获取参数列表 Class<?>[] parameterTypes = getSuperNumber.getParameterTypes(); System.out.println("ParameterTypes: " + Arrays.toString(parameterTypes)); // 方法名 System.out.println("GetSupperNumber Name: " + getSuperNumber.getName()); // 获取属性类型 Field number = clazz.getField("number"); Class<?> type = number.getType(); System.out.println("Field Type: " + type); // 获取类的注解 // 其他获取注解的方法, 详见 注解 http://blog.csdn.net/rozol/article/details/77758192 文章 Annotation[] classAnnotations = clazz.getAnnotations(); System.out.println("ClassAnnotations: " + Arrays.toString(classAnnotations)); } }
动态代理
Proxy 动态代理: 用来修改已经具有的对象的方法, 控制方法是否执行, 或在方法执行之前和执行之后做一些额外的操作jdk动态代理是由Java内部的反射机制来实现的
jdk动态代理需要基于同一的 接口
/** * Proxy 动态代理 * 用来修改已经具有的对象的方法, 控制方法是否执行, 或在方法执行之前和执行之后做一些额外的操作 * jdk动态代理是由Java内部的反射机制来实现的 * jdk动态代理需要基于同一的 接口 * @author Luzhuo */ public class ProxyTest { public static void main(String[] args) { User userProxy = initAccess(new ProxyTest.UserImpl()); System.out.println(userProxy.getName()); System.out.println(userProxy.getAge()); } public static User initAccess(final User user){ User userProxy = (User)Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("getName".equals(method.getName())){ System.out.println("getName() 调用之前"); Object result = method.invoke(user, args); System.out.println("getName() 调用之后"); return result; } return method.invoke(user, args); } }); return userProxy; } public static interface User { public String getName(); public int getAge(); } public static class UserImpl implements User { @Override public String getName() { System.out.println("UserServiceImpl - getName"); return "name"; } @Override public int getAge() { System.out.println("UserServiceImpl - getAge"); return 12; } } }
输出结果:
getName() 调用之前 UserServiceImpl - getName getName() 调用之后 name UserServiceImpl - getAge 12
相关文章推荐
- 【Java核心技术】类型信息(Class对象 反射 动态代理)
- 动态代理---动态生成java文件并编译成class文件
- java.lang.Class<T> -- 反射机制及动态代理
- Class对象、反射、动态代理
- java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象
- 关于使用动态代理创建代理对象是报错 java.lang.ClassCastException: $Proxy0 cannot be cast to 的解决办法
- java语言反射的概述以及三种获取字节码文件对应的Class类型的对象的方式
- java反射1—获取class文件对象
- 动态代理---动态生成java文件并编译成class文件
- 反射机制_介绍_Class对象获取_动态操作_构造器_方法_属性JAVA211-212
- 如何利用java的反射机制动态的取得对象的属性?
- java中如何使用asm动态的生成或修改一个class文件以及asm的架构思想
- 23-java基础加强(反射、泛型、注解、动态代理)
- Java数组反射实现动态的判断一个对象书否是数组,并且对数组进行拆包输出 。。
- 【转】java的反射机制中的动态代理代理(二)--在远程方法调用中运用代理类
- java的cglib动态代理报java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter
- 使用自动生成java文件和自动编译的动态代理模式
- java中利用动态代理,生成"空"对象的例子
- 【转】java的反射机制中的动态代理代理(一)--简介
- Java反射与动态代理