4、在运行时可以调用任意对象的任意方法
Method: invoke(对象,实参列表)步骤: (1)获取Class对象 (2)得到方法Method对象
@Test public void test01()throws Exception{ //(1)获取Class对象:四种方式之一 Class clazz = Class.forName("com.atguigu.ext.demo.AtGuiguDemo"); //(2)得到方法Method对象 //例如:得到void setInfo(String info)方法 /* * (1)Method clazz.getMethod(name, parameterTypes):得到公共的方法 * (2)Method clazz.getDeclaredMethod(name, parameterTypes):得到声明的方法 * 一个类中方法是可能重载,如何定位到某一个方法 方法名 + 形参列表 */ Method method = clazz.getDeclaredMethod("setInfo", String.class); //(3)调用方法 /* * 静态方法: * 类名.方法(【实参列表】) * 非静态方法 * 对象名.方法(【实参列表】) */ //①创建对象 Object obj = clazz.newInstance(); //②调用方法 method.invoke(obj, "at硅谷"); System.out.println(obj); // (4)获取public static void test(int a) //测试自定义的test方法 Method testMethod = clazz.getDeclaredMethod("test", int.class); //调用方法 testMethod.invoke(null, 10);//如果obj位置传入null,表示调用静态方法 }test方法
5、在运行时读取某个注解信息
一个完整的注解,有三个要素: (1)声明 (2)使用 (3)读取
像@Override,@SuppressWarings,@Deprecated等这些是JRE中声明的,也是由编译器读取的 像@Test,@Before…等这些注解是JUnit声明和读取的 像@author,@param…等这些注解是JRE中声明的,由javadoc.exe读取的 … 我们程序员只负责使用。
如果我们自定义的注解,那么声明和读取我们就要自己编写了
获取类上面的注解 步骤: (1)获取Class对象 (2)获取注解对象 (3)获取注解的配置参数的值
//复习:还有静态导入 //声明注解 @Target({TYPE,FIELD}) @interface MyAnnotation{ String value(); //配置参数是value的好处:如果配置参数只有一个,名称是value,在使用时,赋值的话就可以省略"value=" } //使用注解 @MyAnnotation("尚硅谷") //也可以写为:@MyAnnotation(value="尚硅谷"),一般省略写 class MyClass{ @MyAnnotation("尚硅谷") private String info; } public class TestAnnotation { @SuppressWarnings("unchecked") @Test public void test01() { //(1)获取Class对象 Class clazz = MyClass.class;//四种方式之一 //(2)获取注解对象 /* Annotation annotation = clazz.getAnnotation(MyAnnotation.class); annotation.value()会报错,提示annotation没有value这个属性,原因是Annotation是所有注解的父类,就像Object一样,需要向下转型 */ //向下转型 MyAnnotation annotation = (MyAnnotation)clazz.getAnnotation(MyAnnotation.class); //返回一个MyAnnotation对象 //(3)获取注解的配置参数的值(一般注解都是为了拿参数值) String value = annotation.value(); System.out.println("value = " + value); }运行结果:String value = annotation.value();报错空指针 原因:注解生命周期,@Retention(RetentionPolicy.RUNTIME)//只有生命周期是运行时,那么才可以被反射读取 改正后声明注解代码(其它不变):
//声明注解 @Target({TYPE,FIELD}) @Retention(RetentionPolicy.RUNTIME)//只有生命周期是运行时,那么才可以被反射读取 @interface MyAnnotation{ String value(); //如果配置参数只有一个,名称是value,在使用时,赋值的话就可以省略"value=" }再运行
若是将注解写在属性上面:
@MyAnnotation("尚硅谷") //也可以写为:@MyAnnotation(value="尚硅谷"),一般省略写 class MyClass{ @MyAnnotation("atguigu") private String info; } 获取属性上的注解,多一步获取属性上面的注解 步骤: (1)获取Class对象 (2)获取属性对象Field对象 (3)获取注解对象Annotation (4)获取注解的配置参数的值
@SuppressWarnings("unchecked") @Test public void test02() throws NoSuchFieldException, SecurityException { //(1)获取Class对象 Class clazz = MyClass.class;//四种方式之一 //(2)获取属性对象 Field infoField = clazz.getDeclaredField("info"); //(3)获取注解对象 MyAnnotation annotation = (MyAnnotation) infoField.getAnnotation(MyAnnotation.class); //(4)获取注解的配置参数的值 String value = annotation.value(); System.out.println("value = " + value); }