反射
反射机制读取注解
public class StudentTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class clazz = (Class) Class.forName(“d_20180420_1.Student”);
// 获取此类的所有注解
Annotation[] annotations = clazz.getAnnotations();
// 遍历所有的注解
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 根据注解的名字获得指定的注解
MyTable myTable = clazz.getAnnotation(MyTable.class);
System.out.println(myTable.value());
// 获得类的属性的注解
Field field = clazz.getDeclaredField("name");
MyField myField = field.getAnnotation(MyField.class);
System.out.println(myField.columnName() + "\t" + myField.type() + "\t" + myField.length());
}
}
反射机制
reflection指的是可以于运行时加载、探知、使用编译期间完全未知的类。
程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
Class clazz = Class.forName(“xxx.xxx.xxx”);
加载完类之后,在堆内存中,就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为反射。
反射机制的常见作用
动态加载类、动态获取类的信息(属性、方法、构造器)
动态构造对象
动态调用类和对象的任意方法、构造器
动态调用和处理属性
获取泛型信息
处理注解
Class类的对象如何获取
运用getClass()
运用Class.forName();
运用.class
反射机制性能问题
method cost time : 18ms
method1 cost time : 7062ms
method2 cost time : 4280ms
method cost time : 1553ms
method1 cost time : 7007ms
method2 cost time : 4253ms
1000000000L
setAccessible
启用和禁用访问安全检查的开关,值为true则指示反射的对象在使用时应该取消java语言访问检查。值为false则指示反射的对象应该实施java语言访问检查。并不是true就能访问false就不能访问。
禁止安全检查,可以提高反射的运行速度。
动态编译
jdk6引入了动态编译机制
动态编译的应用场景:
可以做一个浏览器端编写java代码,上传服务器编译和运行的在线评测系统。
服务器动态加载某些类文件进行编译
动态编译的两种做法:
通过Runtime调用javac,启动新的进程去操作
Runtime run = Runtime.getRuntime();
Process process = run.exec("javac -cp d:/colin/fileTest/ HelloWorld ");
通过JavaCompiler动态编译
public class CompilerTest {
public static int compilerFile(String sourceFile) {
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
int result = javaCompiler.run(null, null, null, sourceFile);
System.out.println(result == 0 ? “编译成功” : “编译失败”);
return result;
}
public static void main(String[] args) {
compilerFile("");
}
}
第一个参数:为java编译器提供参数
第二个参数:得到java编译器的输出信息
第三个参数:接收编译器的错误信息
第四个参数:可变参数(是一个String数组)能传入一个或多个java源文件
返回值:0表示编译成功,非0表示编译失败
反射操作泛型Generic
java采用泛型擦除的机智来引入泛型。java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除。
为了通过反射操作这些类型以迎合实际开发的需要,java就新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
ParameterizedType表示一种参数化的类型,比如Collection
GenericArrayType 表示一种元素类型是参数化类型或者类型变量的数据类型
TypeVariable 表示各种类型变量的公共父接口
WildcardType 表示一种通配符类型表达式,比如?, ? extends Number, ? super Integer