深入Java反射机制 水深无声 2022-03-22 11:09 231阅读 0赞 **目录** 1 Java反射机制 1.1 RTTI 1.2 Java反射机制是啥 1.2.1 类Class 1.2.2 Object类 1.2.3 利用Class类来创建实例 2 Java静态代理 2.1 代理模式一般涉及到的角色 2.2 静态代理例子 2.3 静态代理的优缺点 2.3.1 优点 2.3.2 缺点 3 Java动态代理 3.1 java.lang.reflect.Proxy 3.2 java.lang.reflect.InvocationHandler 3.3 动态代理实例 3.4 动态代理的优缺点 -------------------- # 1 Java反射机制 # 获取Java运行时的类型信息有两种方法 1. RTTI(Run-Time Type Identification):运行时的类型的识别 2. Java反射机制 ## 1.1 RTTI ## ![20190128102425392.png][] Shape类,三个子类,Circle,Square,Triangle 有一个数组,要去保存Shape类型的对象,实际上存的都是它的子类对象。 当从数组中取出元素时,会自动将结果转型回Shape。这是RTTI最基本的使用形式,因为在Java中,所有的类型转换都是在运行时进行正确的检查的。 大部分代码尽可能少地了解对象的具体类型,而至于对象家族中的一个通用表示打交道。如上述例子中的Shape。 ## 1.2 Java反射机制是啥 ## 运行状态中,能知道任意一个类的所有属性和方法;能调用任意一个对象的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。 ### 1.2.1 类Class ### 程序运行时,java系统会一直对所有对象进行运行时类型识别,这项信息记录了每个对象所属的类。通过专门的类可以访问这些信息。用来保存这些信息的类是Class类。 Class类是Java一个基础类,每装载一个新类时,JVM就会在Java堆中,创建一个Class的实例,这个实例就代表这个Class类型,通过实例获取类型信息。 Method[] getMethods() Field[] getFields() Constructor<?>[] getDeclaredConstructors() ### 1.2.2 Object类 ### clone() Creates and returns a copy of this object. boolean equals(Object obj) protected void finalize() Called by the garbage collector on an object int hashCode() void notify() void notifyAll() String toString() void wait() ### 1.2.3 利用Class类来创建实例 ### 构造Class对象有3种方式 **Class.forName()** Class clazz; try { clazz = Class.forName("java.lang.String"); //clazz.newInstance() is deprecated Object obj = clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } **类.class** Class stringClass = String.class; System.out.println(stringClass); **Object.getClass()** String str = "s"; System.out.println(str.getClass()); 运行结果:class java.lang.String # 2 Java静态代理 # 某些情况下,一个客户不想或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 代理模式的作用:为其他对象提供一种代理以控制对这个对象的访问。 ![20190128135141445.png][] ## 2.1 代理模式一般涉及到的角色 ## **抽象角色:**声明真实对象和代理对象的共同接口 **代理角色:**代理对象角色内含有对真实对象的引用 **真实角色:**代理角色所代表的真实对象,即最终要引用的对象 ## 2.2 静态代理例子 ## //真实对象和代理对象的共同接口 abstract class Subject { public abstract void request(); } //真实角色 class RealSubject extends Subject{ public void request() { System.out.println("From Real Subject!"); } } //代理角色 class ProxySubject extends Subject{ //代理对象内部含有对真实对象的引用 private RealSubject realSubject; public void request() { //在真实角色操作之前所附加的操作 preRequest(); //真实角色所完成的事情 if(null == realSubject) realSubject = new RealSubject(); realSubject.request(); //在真实角色操作之后所附加的操作 postRequest(); } private void preRequest() { System.out.println("Pre Request..."); } private void postRequest() { System.out.println("Post Request..."); } } public class Client { public static void main(String[] args) { Subject subject = new ProxySubject(); subject.request(); } } ## 2.3 静态代理的优缺点 ## ### 2.3.1 优点 ### 业务类只需关注业务逻辑本身,保证了业务类的重用性。 ### 2.3.2 缺点 ### 代理对象的一个接口只服务于一种类型的对象,若代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 若接口增加一个方法,除了所有实现类要实现这个方法外,所有代理类也需实现此方法。增加了代码维护的复杂度。 # 3 Java动态代理 # ## 3.1 java.lang.reflect.Proxy ## Java动态代理机制的主类,提供了一组静态方法来为一组接口动态地生成代理类及其对象。 //Returns the invocation handler for the specified proxy instance //获取指定代理对象所关联的调用处理器 static InvocationHandler getInvocationHandler(Object proxy) //Returns the Class object for a proxy class given a class loader and an array of interfaces //获取关联于指定类加载器和一组接口的动态代理类的类对象 static Class<?> getProxyClass(ClassLoader loader, Class[] interfaces) //用于判断指定类对象是否是一个动态代理类 static boolean isProxyClass(Class<?> cl) //用于为指定类加载器,一组接口及调用处理器生成动态代理类实例 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ## 3.2 java.lang.reflect.InvocationHandler ## 这是调用处理器接口,自定义了一个invoke()方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。 <table> <tbody> <tr> <td><code><a href="http://tool.oschina.net/uploads/apidocs/jdk_7u4/java/lang/Object.html" rel="nofollow">Object</a></code></td> <td><code><strong><a href="http://tool.oschina.net/uploads/apidocs/jdk_7u4/java/lang/reflect/InvocationHandler.html#invoke%28java.lang.Object,%20java.lang.reflect.Method,%20java.lang.Object%5B%5D%29" rel="nofollow">invoke</a></strong>(<a href="http://tool.oschina.net/uploads/apidocs/jdk_7u4/java/lang/Object.html" rel="nofollow">Object</a> proxy, <a href="http://tool.oschina.net/uploads/apidocs/jdk_7u4/java/lang/reflect/Method.html" rel="nofollow">Method</a> method, <a href="http://tool.oschina.net/uploads/apidocs/jdk_7u4/java/lang/Object.html" rel="nofollow">Object</a>[] args)</code></td> </tr> </tbody> </table> 该方法负责集中处理动态代理类上的所有方法调用。第一个参数是代理类实例,第二个参数是被调用的方法对象,第三个参数是调用参数 ## 3.3 动态代理实例 ## interface Subject1 { public void request1(); } public interface Subject2 { public void request2(); } public class RealSubject implements Subject1,Subject2{ public RealSubject() {} public void request1() { System.out.println("From real subject1."); } public void request2() { System.out.println("From real subject2."); } } class DynamicSubject implements InvocationHandler{ private Object sub; public DynamicSubject() {} public DynamicSubject(Object obj) { sub = obj; } //第一个参数是代理类实例,第二个参数是被调用的方法对象,第三个参数是调用参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling" + method); method.invoke(sub, args); System.out.println("after calling" + method); return null; } } public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); InvocationHandler dynamicSubject = new DynamicSubject(realSubject); Class clazz = realSubject.getClass(); //生成动态代理实例 Subject1 subject1 = (Subject1)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), dynamicSubject); //自动调用dynamicSubject.invoke() subject1.request1(); //只需改下接口就可以了 Subject2 subject2 = (Subject2)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), dynamicSubject); subject2.request2(); } } ## 3.4 动态代理的优缺点 ## # ![20190128170246645.png][] # 深入学习Java的无聊日子 ![20190128171258443.png][] -------------------- **本文学习自** [学堂在线-清华大学-许斌《JAVA程序设计进阶》][-_-_JAVA] [20190128102425392.png]: /images/20220322/e1f9d623b4a24a3ea70ac85849e320ff.png [20190128135141445.png]: /images/20220322/e4e1854806b1495fb85329df77996e03.png [20190128170246645.png]: /images/20220322/863710b1e9774438981680e365c44b4c.png [20190128171258443.png]: /images/20220322/30024ac177a24ee0a55a6341bcf4c8b1.png [-_-_JAVA]: https://xuetangx.com/courses/course-v1:TsinghuaX+30240332+sp/courseware/a2eda432b0924151a1c77ed286aa51f8/cac905c8efcb4ec4b4f58209f6f8908f/
相关 Java反射机制深入解析案例 在Java编程中,反射是一个强大的工具,它允许我们在运行时检查类、接口、字段和方法的信息。下面我们将通过一个实际案例来深入解析Java反射。 案例:获取对象的属性值 假设我 快来打我*/ 2024年09月16日 06:18/ 0 赞/ 13 阅读
相关 Java反射机制深入解析实例 Java的反射机制是一种强大的工具,它允许我们在运行时动态地获取和操作类的信息以及对象。 以一个具体的实例来解析: 假设我们有一个类`Person`,并且有一个`sayHe 素颜马尾好姑娘i/ 2024年09月16日 06:03/ 0 赞/ 8 阅读
相关 Java反射机制深入解析 Java的反射机制是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息。以下是反射机制深入解析的关键点: 1. 类加载:当Java应用需要访问一个类时,Java虚拟机 亦凉/ 2024年09月15日 05:03/ 0 赞/ 7 阅读
相关 Java反射机制深入解析 Java的反射机制是一种强大的工具,它允许程序在运行时检查和修改类、对象及方法的信息。下面对Java反射机制进行深入解析: 1. **Class**:这是反射的主要对象类型, 忘是亡心i/ 2024年09月11日 19:57/ 0 赞/ 44 阅读
相关 JAVA基础 (三)反射 深入解析反射机制 上一篇中已经介绍了一些关于反射的基本概念,这篇主要通过一个实例说一说反射的过程,以及实际中应用的例子。 这个例子是这样的设计思路:从一个属性文件中读取一段字符串, 旧城等待,/ 2022年08月11日 16:32/ 0 赞/ 166 阅读
相关 JAVA基础 (二)反射 深入解析反射机制 在谈论到反射这个问题时,你是否有如下疑问? 无论是在.NET还是Java中反射的原理和机制是一样的,理解了一种另一种就可以迎刃而解,想要理解反射首先需 女爷i/ 2022年08月11日 15:30/ 0 赞/ 172 阅读
相关 Java反射机制深入研究 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否 「爱情、让人受尽委屈。」/ 2022年06月14日 11:25/ 0 赞/ 194 阅读
相关 深入理解java反射机制 (转自:[https://blog.csdn.net/u012585964/article/details/52011138][https_blog.csdn.net_u012 悠悠/ 2022年05月24日 10:08/ 0 赞/ 253 阅读
相关 深入Java反射机制 目录 1 Java反射机制 1.1 RTTI 1.2 Java反射机制是啥 1.2.1 类Class 1.2.2 Object类 1.2.3 利用Class类来创建 水深无声/ 2022年03月22日 11:09/ 0 赞/ 232 阅读
还没有评论,来说两句吧...