Java基础24–反射的应用4&5
反射的应用4:动态的调用任意对象的任意方法
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:动态的读取注解
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);
}