zoukankan      html  css  js  c++  java
  • JAVA反射

    参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1255945147512512

    基本逻辑

      1 package reflection;
      2 
      3 import java.lang.reflect.Constructor;
      4 import java.lang.reflect.Field;
      5 import java.lang.reflect.Method;
      6 
      7 /**
      8  * 教程:https://www.liaoxuefeng.com/wiki/1252599548343744/1264799402020448
      9  * class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。
     10  * 每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。注意:这里的Class类型是一个名叫Class的class。
     11  */
     12 public class MainTest2 {
     13 
     14     public static void main(String[] args) {
     15         /**
     16          * 由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、
     17          * 所有方法、字段等,因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。
     18          *
     19          * 这种通过Class实例获取class信息的方法称为反射(Reflection)。
     20          *
     21          * 如何获取一个class的Class实例?有三个方法:
     22          */
     23 
     24 
     25         // 方法1
     26         Class cls1 = String.class;
     27 
     28         // 方法2
     29         String s = "Hello";
     30         Class cls2 = s.getClass();  // 通过实例变量的getClass()获得
     31 
     32         // 方法3
     33         try {
     34             Class cls3 = Class.forName("java.lang.String");
     35         } catch (ClassNotFoundException e) {
     36             e.printStackTrace();
     37         }
     38 
     39         // 因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:
     40 
     41 
     42         /**通过Class实例获取相关信息**/
     43         Class clsStu = Student.class;
     44 
     45         System.out.println(clsStu.getClassLoader());
     46         System.out.println(clsStu.getName());
     47         try {
     48             System.out.println(clsStu.getConstructor());
     49         } catch (NoSuchMethodException e) {
     50             e.printStackTrace();
     51         }
     52         System.out.println(clsStu.getDeclaredFields().toString());
     53         System.out.println(clsStu.getFields().toString());
     54         try {
     55             System.out.println(clsStu.getField("grade"));
     56         } catch (NoSuchFieldException e) {
     57             e.printStackTrace();
     58         }
     59         try {
     60             System.out.println(clsStu.getField("score"));
     61         } catch (NoSuchFieldException e) {
     62             e.printStackTrace();
     63         }
     64         try {
     65             System.out.println(clsStu.getField("name"));
     66             Field field = clsStu.getField("name");
     67             System.out.println("type=" + field.getType() + ", name=" + field.getName() + ", ");
     68         } catch (NoSuchFieldException e) {
     69             e.printStackTrace();
     70         }
     71 
     72 
     73 
     74         try {
     75 
     76             /**通过Class实例调用方法**/
     77             String str = "helloWorld";
     78             Class clsz1 = str.getClass();
     79             Class clsz2 = String.class;
     80             Class clsz3 = Class.forName("java.lang.String");
     81 
     82             System.out.println("1Equal2:" + clsz1.equals(clsz2) + ", 1Equal3:" + clsz1.equals(clsz3));  // true  true
     83             System.out.println("1==2:" + (clsz1 == clsz2) + ", 1==3:" + (clsz1 == clsz3));  // true  true
     84 
     85             Method method = clsz2.getMethod("substring", int.class, int.class);
     86             System.out.println("substring=" + method.invoke(str, 0, 3));
     87 
     88 
     89 
     90             Method m = Integer.class.getMethod("parseInt", String.class);
     91             // 调用该静态方法parseInt,无需传入对象(传null即可)
     92             Integer n = (Integer) m.invoke(null, "12345");
     93             System.out.println("n=" + n);
     94 
     95 
     96             /**通过Class实例调用构造方法**/
     97             Person p1 = new Person();
     98             Person p2 = Person.class.newInstance();  // 调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法
     99             System.out.println("p1.equals.p2:"  + p1.equals(p2));  // false
    100             System.out.println("p1==p2:"  + p1.equals(p2));  // false
    101 
    102             // 使用 Java的反射API提供的Constructor对象
    103             Constructor constructor1 = Integer.class.getConstructor(String.class);  // 获取Integer参数类型为String的构造方法
    104             int resInt = (int) constructor1.newInstance("987");
    105             System.out.println("resInt=" + resInt);
    106 
    107 
    108 
    109         } catch (Exception e) {
    110             e.printStackTrace();
    111         }
    112 
    113 
    114     }
    115 
    116     static class Person{
    117         public String name;
    118     }
    119 
    120     class Student extends Person {
    121         public int score;
    122         private int grade;
    123     }
    124 }
    View Code

    执行结果:

    /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/lib/tools.jar:/Users/wuxiong.wx/work/code/testDemo/target/classes:/Users/wuxiong.wx/.m2/repository/org/springframework/spring/999-not-exist/spring-999-not-exist.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-core/4.3.2.RELEASE/spring-core-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-beans/4.3.2.RELEASE/spring-beans-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-aop/4.3.2.RELEASE/spring-aop-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-context/4.3.2.RELEASE/spring-context-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-expression/4.3.2.RELEASE/spring-expression-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-context-support/4.3.2.RELEASE/spring-context-support-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-tx/4.3.2.RELEASE/spring-tx-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-jdbc/4.3.2.RELEASE/spring-jdbc-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-orm/4.3.2.RELEASE/spring-orm-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-web/4.3.2.RELEASE/spring-web-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-webmvc/4.3.2.RELEASE/spring-webmvc-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/springframework/spring-test/4.3.2.RELEASE/spring-test-4.3.2.RELEASE.jar:/Users/wuxiong.wx/.m2/repository/org/aspectj/aspectjrt/1.8.8/aspectjrt-1.8.8.jar:/Users/wuxiong.wx/.m2/repository/org/aspectj/aspectjweaver/1.8.8/aspectjweaver-1.8.8.jar:/Users/wuxiong.wx/.m2/repository/junit/junit/4.12/junit-4.12.jar:/Users/wuxiong.wx/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/wuxiong.wx/.m2/repository/io/appium/java-client/7.0.0/java-client-7.0.0.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-java/3.141.59/selenium-java-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-chrome-driver/3.141.59/selenium-chrome-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-edge-driver/3.141.59/selenium-edge-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-firefox-driver/3.141.59/selenium-firefox-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-ie-driver/3.141.59/selenium-ie-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-opera-driver/3.141.59/selenium-opera-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-remote-driver/3.141.59/selenium-remote-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-safari-driver/3.141.59/selenium-safari-driver-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/net/bytebuddy/byte-buddy/1.8.15/byte-buddy-1.8.15.jar:/Users/wuxiong.wx/.m2/repository/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar:/Users/wuxiong.wx/.m2/repository/com/google/guava/guava/25.0-jre/guava-25.0-jre.jar:/Users/wuxiong.wx/.m2/repository/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:/Users/wuxiong.wx/.m2/repository/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0.jar:/Users/wuxiong.wx/.m2/repository/com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3.jar:/Users/wuxiong.wx/.m2/repository/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar:/Users/wuxiong.wx/.m2/repository/org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar:/Users/wuxiong.wx/.m2/repository/com/squareup/okhttp3/okhttp/3.11.0/okhttp-3.11.0.jar:/Users/wuxiong.wx/.m2/repository/com/squareup/okio/okio/1.14.0/okio-1.14.0.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-support/3.141.59/selenium-support-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/org/seleniumhq/selenium/selenium-api/3.141.59/selenium-api-3.141.59.jar:/Users/wuxiong.wx/.m2/repository/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar:/Users/wuxiong.wx/.m2/repository/org/apache/httpcomponents/httpclient/4.5.6/httpclient-4.5.6.jar:/Users/wuxiong.wx/.m2/repository/org/apache/httpcomponents/httpcore/4.4.10/httpcore-4.4.10.jar:/Users/wuxiong.wx/.m2/repository/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/Users/wuxiong.wx/.m2/repository/cglib/cglib/3.2.8/cglib-3.2.8.jar:/Users/wuxiong.wx/.m2/repository/org/ow2/asm/asm/6.2.1/asm-6.2.1.jar:/Users/wuxiong.wx/.m2/repository/org/apache/ant/ant/1.10.3/ant-1.10.3.jar:/Users/wuxiong.wx/.m2/repository/org/apache/ant/ant-launcher/1.10.3/ant-launcher-1.10.3.jar:/Users/wuxiong.wx/.m2/repository/commons-validator/commons-validator/1.6/commons-validator-1.6.jar:/Users/wuxiong.wx/.m2/repository/commons-beanutils/commons-beanutils/1.9.2/commons-beanutils-1.9.2.jar:/Users/wuxiong.wx/.m2/repository/commons-digester/commons-digester/1.8.1/commons-digester-1.8.1.jar:/Users/wuxiong.wx/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/wuxiong.wx/.m2/repository/org/apache/commons/commons-lang3/3.8/commons-lang3-3.8.jar:/Users/wuxiong.wx/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar:/Users/wuxiong.wx/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/Users/wuxiong.wx/.m2/repository/com/alibaba/fastjson/1.2.60/fastjson-1.2.60.jar reflection.MainTest2
    sun.misc.Launcher$AppClassLoader@135fbaa4
    reflection.MainTest2$Student
    [Ljava.lang.reflect.Field;@7ea987ac
    [Ljava.lang.reflect.Field;@5cad8086
    public int reflection.MainTest2$Student.score
    public java.lang.String reflection.MainTest2$Person.name
    type=class java.lang.String, name=name, 
    1Equal2:true, 1Equal3:true
    1==2:true, 1==3:true
    substring=hel
    n=12345
    p1.equals.p2:false
    p1==p2:false
    resInt=987
    java.lang.NoSuchMethodException: reflection.MainTest2$Student.<init>()
        at java.lang.Class.getConstructor0(Class.java:3082)
        at java.lang.Class.getConstructor(Class.java:1825)
        at reflection.MainTest2.main(MainTest2.java:48)
    java.lang.NoSuchFieldException: grade
        at java.lang.Class.getField(Class.java:1703)
        at reflection.MainTest2.main(MainTest2.java:55)
    
    Process finished with exit code 0

    动态代理

    https://www.liaoxuefeng.com/wiki/1252599548343744/1264804593397984

    另外的总结:https://www.zhihu.com/question/20794107/answer/604485904

    有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?

    这是可能的,因为Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实例。

    什么叫运行期动态创建?听起来好像很复杂。所谓动态代理,是和静态相对应的。我们来看静态代码怎么写:

    定义接口:

    1 public interface Hello {
    2     void morning(String name);
    3 }

    编写实现类:

    1 public class HelloWorld implements Hello {
    2     public void morning(String name) {
    3         System.out.println("Good morning, " + name);
    4     }
    5 }

    创建实例,转型为接口并调用:

    1 Hello hello = new HelloWorld();
    2 hello.morning("Bob");

    还有一种方式是动态代码,我们仍然先定义了接口Hello,但是我们并不去编写实现类,而是直接通过JDK提供的一个Proxy.newProxyInstance()创建了一个Hello接口对象。这种没有实现类但是在运行期动态创建了一个接口对象的方式,我们称为动态代码。JDK提供的动态创建接口对象的方式,就叫动态代理。

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 import java.lang.reflect.Proxy;
     4 
     5 public class Main {
     6     public static void main(String[] args) {
     7         InvocationHandler handler = new InvocationHandler() {
     8             @Override
     9             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    10                 System.out.println(method);
    11                 if (method.getName().equals("morning")) {
    12                     System.out.println("Good morning, " + args[0]);
    13                 }
    14                 return null;
    15             }
    16         };
    17         Hello hello = (Hello) Proxy.newProxyInstance(
    18             Hello.class.getClassLoader(), // 传入ClassLoader
    19             new Class[] { Hello.class }, // 传入要实现的接口
    20             handler); // 传入处理调用方法的InvocationHandler
    21         hello.morning("Bob");
    22     }
    23 }
    24 
    25 interface Hello {
    26     void morning(String name);
    27 }
    View Code
    public abstract void Hello.morning(java.lang.String)
    Good morning, Bob

    例:

     1 package designpattern.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.InvocationTargetException;
     5 import java.lang.reflect.Method;
     6 import java.lang.reflect.Proxy;
     7 
     8 public class DynamicProxyTest {
     9 
    10     public static void main(String[] args) {
    11         AbstractSubject abstractSubject = null;
    12         InvocationHandler invocationHandler = null;
    13 
    14         // jdk动态代理 设置此系统属性,让JVM生成的Proxy类写入文件
    15         System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    16 
    17         invocationHandler = new DynamicProxy(new RealSubjectA());
    18         abstractSubject = (AbstractSubject) Proxy.newProxyInstance(
    19                 AbstractSubject.class.getClassLoader(),
    20                 new Class[] {AbstractSubject.class},
    21                 invocationHandler);
    22 
    23         abstractSubject.request();
    24 
    25     }
    26 
    27 
    28 }
    29 
    30 interface AbstractSubject {
    31     void request();
    32 }
    33 
    34 
    35 class RealSubjectA implements AbstractSubject {
    36 
    37     public void request() {
    38         System.out.println("访问真实主题A");
    39     }
    40 }
    41 
    42 class RealSubjectB implements AbstractSubject {
    43 
    44     public void request() {
    45         System.out.println("访问真实主题B");
    46     }
    47 }
    48 
    49 
    50 /**
    51  * 代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,
    52  * 代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。
    53  */
    54 class DynamicProxy implements InvocationHandler {
    55 
    56     Object object;
    57 
    58     public DynamicProxy(Object object) {
    59         this.object = object;
    60     }
    61 
    62     public Object invoke(Object proxy, Method m, Object[] args) {
    63         try {
    64             beforeRequest();
    65             m.invoke(object, args);  // 这里第一个参数是object,而不是p
    66             afterRequest();
    67         } catch (IllegalAccessException e) {
    68             e.printStackTrace();
    69         } catch (InvocationTargetException e) {
    70             e.printStackTrace();
    71         }
    72 
    73         return null;
    74     }
    75 
    76     void beforeRequest() {
    77         System.out.println("预处理");
    78     }
    79 
    80     void afterRequest() {
    81         System.out.println("后处理");
    82     }
    83 }
    预处理
    访问真实主题A
    后处理
  • 相关阅读:
    Java集合框架之Set接口浅析
    Java集合框架之Vector浅析
    Java集合框架之LinkedList浅析
    Java集合框架之ArrayList浅析
    Java集合框架之List接口浅析
    数据库设计==>>MySchool
    Windows程序==>>使用ListView控件展示数据
    Windows程序控件升级==>>构建布局良好的Windows程序
    窗体==>>初始Windows程序
    数据库的有关知识==>>我们的血泪史之经典练习(1-2)
  • 原文地址:https://www.cnblogs.com/wxdlut/p/15547739.html
Copyright © 2011-2022 走看看