参考: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