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,表示调用静态方法
	}

java 引用动态类_java 引用动态类


test方法

java 引用动态类_java_02

反射的应用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="
}

再运行

java 引用动态类_静态方法_03

若是将注解写在属性上面:

@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);
	}

java 引用动态类_Test_04