1、注解 1.1、 内置注解
1.2、元注解 元注解的作用就是负责注解
其它注解。
1.3、自定义注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.lang.annotation.*;@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @interface MyAnnotation1{ int age () ; String[] hobby() default {"dance" , "sing" }; } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ String value () ; }
注解中的参数一定要加()
!
当注解只有一个参数时,参数名可以定义为 value
,在调用的时候直接赋值就行。
1 2 3 4 5 public class MyAnnotationTest { @MyAnnotation1(age = 12) @MyAnnotation2("value") String name; }
2、反射 Java 反射就是在运行
状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,并且能改变它的属性。
2.1、获取 Class 类的实例
通过类的 class 属性获取,安全可靠,性能最高。
Class clz = Person.class;
调用实例的 getClass() 方法。
Class clz = person.getClass();
通过 Class.forName() 获取。
Class clz = Class.forName("com.yqx.Person");
1 2 3 4 5 6 7 8 @Test public void test1 () throws ClassNotFoundException { Class clz1 = Person.class; Class clz2 = new Person().getClass(); Class clz3 = Class.forName("Person" ); System.out.println(clz1 == clz2); System.out.println(clz2 == clz3); }
2.2、拥有 Class 对象的类型
class:外部类,成员,局部内部类,匿名内部类。
interface:接口
[]:数组
enum:枚举
annotation:注解 @interface
primitive type:基本数据类型
void
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Test public void test2 () { Class clz1 = Object.class; Class clz2 = Comparable.class; Class clz3 = String[].class; Class clz4 = String[][].class; Class clz5 = Override.class; Class clz6 = ElementType.class; Class clz7 = Integer.class; Class clz8 = void .class; Class clz9 = Class.class; System.out.println(clz1); System.out.println(clz2); System.out.println(clz3); System.out.println(clz4); System.out.println(clz5); System.out.println(clz6); System.out.println(clz7); System.out.println(clz8); System.out.println(clz9); int [] a = new int [10 ]; int [] b = new int [100 ]; System.out.println(a.getClass() == b.getClass()); }
打印输出 (数组即使长度不同,其 Class 类也都是相同的)
1 2 3 4 5 6 7 8 9 10 11 12 class java .lang .Object interface java .lang .Comparable class [Ljava .lang .String ;class [[Ljava .lang .String ;interface java .lang .Override class java .lang .annotation .ElementType class java .lang .Integer void class java .lang .Class true Process finished with exit code 0
2.3、类的加载
2.4、获取类的属性及方法 反射机制允许程序在运行时取得任何一个已知名称的 class 的内部信息,包括包括其modifiers (修饰符),fields (属性),methods (方法)等,并可于运行时改变 fields 内容或调用 methods。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Test public void test3 () throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { Class c1 = Class.forName("Person" ); Person person1 = (Person) c1.newInstance(); System.out.println(person1); Constructor constructor = c1.getDeclaredConstructor(String.class, int .class); Person person2 = (Person) constructor.newInstance("yqx" , 20 ); System.out.println(person2); Method method1 = c1.getDeclaredMethod("getName" ); Method method2 = c1.getDeclaredMethod("setName" , String.class); String name1 = (String) method1.invoke(person1); method2.invoke(person1, "deflory" ); String name2 = (String) method1.invoke(person1); System.out.println("Before: " + name1); System.out.println("After: " + name2); Field field = c1.getDeclaredField("age" ); field.setAccessible(true ); field.set(person1, 18 ); System.out.println(person1.getAge()); }
打印内容
1 2 3 4 5 6 7 Person{name='null' , age=0 } Person{name='yqx' , age=20 } Before: null After: deflory 18 Process finished with exit code 0
2.5、性能测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Test public void test4 () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Person person = new Person(); long start = System.currentTimeMillis(); for (int i=0 ;i<1e9 ;i++){ person.getAge(); } long end = System.currentTimeMillis(); System.out.println("普通方法用时:" + (end - start) + "ms" ); Method method = Person.class.getDeclaredMethod("getAge" ); start = System.currentTimeMillis(); for (int i=0 ;i<1e9 ;i++){ method.invoke(person); } end = System.currentTimeMillis(); System.out.println("反射(检测开启)用时:" + (end - start) + "ms" ); method.setAccessible(true ); start = System.currentTimeMillis(); for (int i=0 ;i<1e9 ;i++){ method.invoke(person); } end = System.currentTimeMillis(); System.out.println("反射(检测关闭)用时:" + (end - start) + "ms" ); }
打印内容
1 2 3 4 5 普通方法用时:1379ms 反射(检测开启)用时:1863ms 反射(检测关闭)用时:1591ms Process finished with exit code 0
2.6、反射操作泛型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Test public void test5 () throws NoSuchMethodException { Method test01 = Person.class.getDeclaredMethod("test01" , Map.class, List.class); Method test02 = Person.class.getDeclaredMethod("test02" ); System.out.println("test01(参数泛型)" ); Type[] genericParameterTypes = test01.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); } } } System.out.println("\ntest02(返回值泛型)" ); Type getGenericReturnType = test02.getGenericReturnType(); System.out.println(getGenericReturnType); if (getGenericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) getGenericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments){ System.out.println(actualTypeArgument); } } }
打印内容
1 2 3 4 5 6 7 8 9 10 11 12 13 test01(参数泛型) java.util.Map<java.lang.String, java.lang.Integer> class java .lang .String class java .lang .Integer java .util .List <java .lang .Character >class java .lang .Character test02 (返回值泛型)java .util .Map <java .lang .String , java .lang .Integer >class java .lang .String class java .lang .Integer Process finished with exit code