JAVA-反射

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

 

基本逻辑

JAVA-反射
  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提供的动态创建接口对象的方式,就叫动态代理。

JAVA-反射
 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

 

上一篇:leetcode331 验证二叉树的前序序列化 golang


下一篇:手撸golang GO与微服务 Saga模式之2