Java-反射
反射是程序的自我分析能力,通过反射可以确定类有哪些方法、有哪些构造方法以及有哪些成员变量。Javay语言提供了反射机制,通过反射机制能够动态读取一个类的信息;能够在运行时动态加载类,而不是在编译期,反射可用于框架开发
它能够从配置文件中读取配置信息动态加载类,创建对象,以及调用方法和成员变量
1.Java反射机制API
Java反射机制API主要是java.lang.Class类和java.lang.reflect包。
1.1Java.lang.Class类
Class类的一个实例表示Java的一种数据类型,包括类、接口、枚举、注解、数组基本数据类型和void。
void是“无类型”,主要用于方法返回值类型的声明,表示不需要返回值。Class没有公有的构造方法,Class实例是由JVM类加载时自动创建。
在Java程序中Class实例可以通过如下代码实现
import org.omg.Messaging.SYNC_WITH_TRANSPORT; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class reflection { public static void main(String[] args) { //1.通过类型class静态变量 Class class1 = String.class; //2.通过对象的getClass()方法 String str = "Hello"; Class class2 = str.getClass(); //获得int类型Class实例 Class class3 = int.class; //获得Integer类型Class实例 Class class4 = Integer.class; System.out.println("class2类名称" + class2.getName()); System.out.println("class2类是否为接口" + class2.isInterface()); System.out.println("class2是否为数组对象" + class2.isArray()); System.out.println("class2父类名称" + class2.getSuperclass().getName()); System.out.println("class1基本类型" + class1.isPrimitive()); System.out.println("class2基本类型" + class2.isPrimitive()); System.out.println("class3基本类型" + class3.isPrimitive()); System.out.println("class4基本类型" + class4.isPrimitive()); } }
运行结果如下:
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:63271,suspend=y,server=n -javaagent:C:\Users\FL\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;E:\编程\eclipseJavaCode\IXml\out\production\IXml;E:\编程\eclipseJavaCode\IXml\lib\jaxws-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxws-rt.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxws-tools.jar;E:\编程\eclipseJavaCode\IXml\lib\activation.jar;E:\编程\eclipseJavaCode\IXml\lib\FastInfoset.jar;E:\编程\eclipseJavaCode\IXml\lib\gmbal-api-only.jar;E:\编程\eclipseJavaCode\IXml\lib\http.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-impl.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr173_api.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr181-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr250-api.jar;E:\编程\eclipseJavaCode\IXml\lib\management-api.jar;E:\编程\eclipseJavaCode\IXml\lib\mimepull.jar;E:\编程\eclipseJavaCode\IXml\lib\policy.jar;E:\编程\eclipseJavaCode\IXml\lib\resolver.jar;E:\编程\eclipseJavaCode\IXml\lib\saaj-api.jar;E:\编程\eclipseJavaCode\IXml\lib\saaj-impl.jar;E:\编程\eclipseJavaCode\IXml\lib\stax-ex.jar;E:\编程\eclipseJavaCode\IXml\lib\streambuffer.jar;E:\编程\eclipseJavaCode\IXml\lib\woodstox.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-xjc.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar" reflection Connected to the target VM, address: '127.0.0.1:63271', transport: 'socket' class2类名称java.lang.String class2类是否为接口false class2是否为数组对象false class2父类名称java.lang.Object class1基本类型false class2基本类型false class3基本类型true class4基本类型false public boolean equals();
1.2java.lang.reflect包
- java.lang..reflect包括了反射中用到的类,主要的类说明如下:
- Constructor类:提供类的构造方法信息。
- Field类:提供类或接口中成员变量信息
- Method类:提供类或接口成员方法信息
- Array类:提供了动态创建和访问Java数组的方法。
- Modifier类:提供类和成员访问修饰符信息
示例代码如下:
import org.omg.Messaging.SYNC_WITH_TRANSPORT; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class reflection { public static void main(String[] args) { try { //动态加载xx类的运行时对象 Class c = Class.forName("java.lang.String"); //获取成员方法集合 Method[] methods = c.getDeclaredMethods(); //遍历方法集合 for (Method method : methods) { //打印权限修饰符,如public、protected、private System.out.print(Modifier.toString(method.getModifiers())); //打印返回值类型名称 System.out.print(" " + method.getReturnType().getName() + " "); //打印方法名称 System.out.println(method.getName() + "();"); System.out.println("\n"); } } catch (ClassNotFoundException e) { System.out.println("找不到指定的类"); } } }
执行结果
public boolean equals(); public java.lang.String toString(); public int hashCode(); public int compareTo(); public volatile int compareTo(); public int indexOf(); public int indexOf();
2.创建对象
Java反射机制提供另外一种创建对象的方法。Class类提供了一个实例方法。Class类提供了一个实例方法newInstance(),通过该方法可以创建对象。
Class clz = Class.forName("java.lang.String"); String str = (String) clz.newInstance();
2.1调用构造方法
调用方法newInstance()创建对象,这个过程中需要调用构造方法,上面的代码只是调用了String的默认构造方法,如果想调用非默认构造方法,则需要使用Constructor对象,它对应着一个构造方法。获得Constructor对象需要使用Class类的如下方法:
- Constructor[] getConstructors():返回所有公共构造方法Constructor对象数组。
- Constructor[] getDeclaredConstructors():返回所有构造方法Constructor对象数组。
- Constructor getConstructor(Class... parameterTypes):根据参数列表返回公有Constructor对象,参数parameterTypes是Class数组,指定构造方法的参数列表。
- Constructor getDeclaredConstuctor(Class...parameterTypes):根据参数列表返回一个Constructor对象,对象parameterTypes同上。
实例代码如下:
import org.omg.Messaging.SYNC_WITH_TRANSPORT; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class reflection { public static void main(String[] args) { try { Class clz = Class.forName("java.lang.String"); //调用默认构造方法 String str1 = (String)clz.newInstance(); //设置构造方法参数类型 Class[] params = new Class[1]; //第一个参数是String params[0] = String.class; //获取与参数对应的构造方法 Constructor constructor = clz.getConstructor(params); //为构造方法传递参数 Object[] argObject =new Object[1]; //第一个参数传递的是“Hello” argObject[0] = "Hello"; //调用非默认构造方法,构造方法第一个参数是String类型 String str2 = (String) constructor.newInstance(argObject); System.out.println(str2); } catch (Exception e) { e.printStackTrace(); } } }
执行结果
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:64608,suspend=y,server=n -javaagent:C:\Users\FL\.IntelliJIdea2019.1\system\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;E:\编程\eclipseJavaCode\IXml\out\production\IXml;E:\编程\eclipseJavaCode\IXml\lib\jaxws-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxws-rt.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxws-tools.jar;E:\编程\eclipseJavaCode\IXml\lib\activation.jar;E:\编程\eclipseJavaCode\IXml\lib\FastInfoset.jar;E:\编程\eclipseJavaCode\IXml\lib\gmbal-api-only.jar;E:\编程\eclipseJavaCode\IXml\lib\http.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-impl.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr173_api.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr181-api.jar;E:\编程\eclipseJavaCode\IXml\lib\jsr250-api.jar;E:\编程\eclipseJavaCode\IXml\lib\management-api.jar;E:\编程\eclipseJavaCode\IXml\lib\mimepull.jar;E:\编程\eclipseJavaCode\IXml\lib\policy.jar;E:\编程\eclipseJavaCode\IXml\lib\resolver.jar;E:\编程\eclipseJavaCode\IXml\lib\saaj-api.jar;E:\编程\eclipseJavaCode\IXml\lib\saaj-impl.jar;E:\编程\eclipseJavaCode\IXml\lib\stax-ex.jar;E:\编程\eclipseJavaCode\IXml\lib\streambuffer.jar;E:\编程\eclipseJavaCode\IXml\lib\woodstox.jar;E:\编程\eclipseJavaCode\IXml\lib\jaxb-xjc.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar" reflection Connected to the target VM, address: '127.0.0.1:64608', transport: 'socket' Hello Disconnected from the target VM, address: '127.0.0.1:64608', transport: 'socket' Process finished with exit code 0