反射机制、自定义Annotation
java反射机制
- 获取运行时类的完整结构
- 可以再运行时的代码可以根据某些条件改变自身结构
- 反射对性能有影响。
- 一个类在内存中只有一个class对象
- 一个类被加载后,类的整个结构都会被封装在class对象中。
测试1-常用反射类、方法
package com.fh.base; import java.lang.reflect.*; import java.util.*; public class T { public static void main(String[] args) throws Exception { getGeneric(); } /** * 获得类实例!!! */ static void getInstance() throws Exception { /*Constructor<Stu> declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class); Stu stu1 = declaredConstructor.newInstance(12,"Jay"); System.out.println("【通过构造器实现类的实例化】" + stu1);*/ Class stuClass = Class.forName("com.fh.base.Stu"); Stu stu = (Stu) stuClass.newInstance(); System.out.println("【new 类的实例化】" + stu); System.out.println("【通过反射操作方法 Method invoke(对象,值)。为哪个对象赋值】"); Method setName = stuClass.getDeclaredMethod("setName", String.class); setName.invoke(stu, "Jay"); System.out.println("【通过反射操作方法 Method invoke(对象)。获取哪个对象的值】"); Method getName = stuClass.getDeclaredMethod("getName"); String name = (String) getName.invoke(stu); System.out.println(name); System.out.println("【通过反射操作属性 Field set(对象,值)"); Field name1 = stuClass.getDeclaredField("name"); name1.setAccessible(true);//java.lang.IllegalAccessException: Class com.fh.base.T can not access a member of class com.fh.base.Stu with modifiers "private" name1.set(stu, "周杰伦"); System.out.println(stu.getName()); } /** * 获得包信息 */ static void getPackeage() { System.out.println("【获得类所在包】"); Class stuClass = Stu.class; Package aPackage = stuClass.getPackage(); System.out.println(aPackage); } /** * 获得Class信息 */ static void getClassz() throws Exception { //System.out.println("【Java 类路径】" + System.getProperty("java.class.path")); System.out.println("【获取类的加载器】" + T.class.getClassLoader() + ";Object根加载器:" + Object.class.getClassLoader()); Class<T> tClass1 = T.class; Class<?> tClass2 = Class.forName("com.fh.base.T"); T t = new T(); Class<? extends T> tClass3 = t.getClass(); System.out.println("【一个类在内存中只有一个class对象】" + (tClass1.hashCode() == tClass2.hashCode() && tClass2.hashCode() == tClass3.hashCode())); System.out.println("【获得类名】" + tClass1.getName()); T t1 = tClass1.newInstance(); T t2 = tClass1.newInstance(); Stu stu = Stu.class.newInstance(); System.out.println("【类的实例化】" + (t1 == t2)); System.out.println("【类的实例化】" + stu); System.out.println("【用来判断A是否是B的实例对象或者B子类的实例对象】" + (t1 instanceof T)); } /** * 获得属性信息 */ static void getField() throws Exception { Class stuClass = Stu.class; System.out.println("【获取所有属性】"); Field[] declaredFields = stuClass.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field); } System.out.println("【获取public属性】"); Field[] fields = stuClass.getFields(); for (Field field : fields) { System.out.println(field); } Field name = stuClass.getDeclaredField("name"); System.out.println("【获取指定属性】" + name); } /** * 获得方法 */ static void getMehtods() throws Exception { Class stuClass = Stu.class; System.out.println("【获取所有方法(包括Object putlic方法)】"); Method[] declaredMethods = stuClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } System.out.println("【获取public方法】"); Method[] methods = stuClass.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("【获取指定方法】"); Method setName = stuClass.getDeclaredMethod("setName", String.class); System.out.println(setName); } /** * 获得构造器 */ static void getConstruct() throws Exception { Class stuClass = Stu.class; System.out.println("【获取所有构造器】"); Constructor[] declaredConstructors = stuClass.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } System.out.println("【获取所有public构造器】"); Constructor[] constructors = stuClass.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } System.out.println("【获取指定构造器】"); Constructor declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class); System.out.println(declaredConstructor); } /** * 反射对性能有影响 */ static void wasteTime() throws Exception { /*******************正常获取属性消耗**********************/ long startTime = System.currentTimeMillis(); Stu stu = new Stu(); for (int i = 0; i < 10_0000_0000; i++) { stu.getName(); } long endTime = System.currentTimeMillis(); System.out.println("正常获取属性消耗:" + (endTime - startTime) + "ms"); /*********************反射获取属性消耗********************/ startTime = System.currentTimeMillis(); Class<?> stuClass = Class.forName("com.fh.base.Stu"); Method getName = stuClass.getDeclaredMethod("getName"); stu = (Stu) stuClass.newInstance(); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(stu); } endTime = System.currentTimeMillis(); System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms"); /*********************反射获取属性消耗********************/ startTime = System.currentTimeMillis(); getName.setAccessible(true); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(stu); } endTime = System.currentTimeMillis(); System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms"); } /** * 反射机制操作泛型 * 泛型擦除机制引入泛型,java中的泛型仅仅是给编译器javac使用的,确保 * 数据的安全性和免去强制类型转换问题。一旦编译完成,所有和泛型有关的类型 * 全部被擦除。 */ static void getGeneric() throws Exception { Method method = Stu.class.getDeclaredMethod("getStu", List.class, Map.class); System.out.println("【获取方法中的所有泛型参数】"); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("***" + genericParameterType); if (genericParameterType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println("【获取泛型参数具体参数】" + actualTypeArgument); } } } method = Stu.class.getDeclaredMethod("getStu"); Type genericReturnType = method.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println("【获取泛型返回值的具体参数】" + actualTypeArgument); } } } } class Stu { private int id; private String name; private String sex; public String hobby; String schooh; private Stu(int id, String name, String sex) { this.id = id; this.name = name; this.sex = sex; } public Stu() { } public Stu(int id, String name) { this.id = id; this.name = name; } public Map<String, Stu> getStu() { return null; } public void getStu(List<Stu> list, Map<String, Stu> map) { } public int getId() { return id; } public Stu setId(int id) { this.id = id; return this; } public String getName() { return name; } public Stu setName(String name) { this.name = name; return this; } public String getSex() { return sex; } public Stu setSex(String sex) { this.sex = sex; return this; } private void test1() { } @Override public String toString() { return "Stu{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + ", hobby='" + hobby + '\'' + ", schooh='" + schooh + '\'' + '}'; } }
测试2-通过反射设置表和类关系映射Annotation
package com.fh.gaoji.anotation; import java.lang.annotation.*; import java.lang.reflect.Field; public class ClassAndTableYingSheTest { public static void main(String[] args) throws NoSuchFieldException { Class<Stu> stuClass = Stu.class; //获取类上的所有注解 Annotation[] annotations = stuClass.getAnnotations(); for (Annotation annotation : annotations) { System.out.println("【获取Stu类所有注解】"+annotation); } //获取ClassAndTable注解 ClassAndTable classAndTable = stuClass.getAnnotation(ClassAndTable.class); System.out.println("【获取指定类注解的值】"+classAndTable.value()); System.out.println("【获取Stu类所有属性】"); Field[] fields = stuClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field =fields[i]; FildAndColum annotation = field.getAnnotation(FildAndColum.class); System.out.println(annotation.name() + "***" +annotation.type() + "***" + annotation.length()); } //获取FildAndColum注解 Field field = stuClass.getDeclaredField("name"); FildAndColum annotation = field.getAnnotation(FildAndColum.class); System.out.println("【获取指定类属性的值】"+annotation.name() + "***" +annotation.type() + "***" + annotation.length()); } } @ClassAndTable("db_student") class Stu{ @FildAndColum(name = "db_id",type = "int",length = 10) private int id; @FildAndColum(name = "db_name",type = "varchar",length = 100) private String name; public int getId() { return id; } public Stu setId(int id) { this.id = id; return this; } public String getName() { return name; } public Stu setName(String name) { this.name = name; return this; } @Override public String toString() { return "Stu{" + "id=" + id + ", name='" + name + '\'' + '}'; } } /** * 类和【表】的映射 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface ClassAndTable{ String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("") } /** * 属性和【列】的映射 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FildAndColum{ String name(); String type(); int length(); } //@Target({ElementType.TYPE,ElementType.METHOD}) //@Retention(RetentionPolicy.RUNTIME) //@interface MyAnnotation1{ // //注解参数:参数类型+参数名() // String name() default "fh";//没有默认值,调用注解必须加上此参数!!! // int age() default 14; // String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("") // String[] school() default {"AA","BB"}; // //}