在运行期探究和使用编译期的内容(编译期配置的注解),要用到Java中的灵魂技术——反射!
1、首先我们需要回顾一下我们之前讲的反射的知识
反射机制:是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信?? ? 息以及动态调用对象方法的功能称为 java 语言的反射机制;
2、反射知识补充:
1)、Method对象,获取method对象:
方法 | 备注 |
---|---|
Method[] getMethods() | 返回所有[公共]成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的Method |
getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象Method |
getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
public class Student {
//私有的,无参无返回值
private void show() {
System.out.println("私有的show方法,无参无返回值");
}
//公共的,无参无返回值
public void function1() {
System.out.println("function1方法,无参无返回值");
}
//公共的,有参无返回值
public void function2(String name) {
System.out.println("function2方法,有参无返回值,参数为" + name);
}
//公共的,无参有返回值
public String function3() {
System.out.println("function3方法,无参有返回值");
return "aaa";
}
//公共的,有参有返回值
public String function4(String name) {
System.out.println("function4方法,有参有返回值,参数为" + name);
return "aaa";
}
}
public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//method1();
//method2();
//method3();
//method4();
//method5();
}
private static void method5() throws ClassNotFoundException, NoSuchMethodException {
// Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
Class clazz = Class.forName("com.aaa.Student");
//获取一个成员方法show
Method method = clazz.getDeclaredMethod("show");
System.out.println(method);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.aaa.Student");
//获取一个有形参的方法function2
Method method = clazz.getMethod("function2", String.class);
System.out.println(method);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
//Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象
Class clazz = Class.forName("com.aaa.Student");
//获取成员方法function1
Method method1 = clazz.getMethod("function1");
System.out.println(method1);
}
private static void method2() throws ClassNotFoundException {
//Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Class clazz = Class.forName("com.aaa.Student");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
private static void method1() throws ClassNotFoundException {
// Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
//1.获取class对象
Class clazz = Class.forName("com.aaa.Student");
//2.获取成员方法对象
Method[] methods = clazz.getMethods();
//3.遍历
for (Method method : methods) {
System.out.println(method);
}
}
}
?2)、使用Method对象运行方法—Object invoke(Object obj, Object... args)运行方法
public class tDemo6 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
// Object invoke(Object obj, Object... args):运行方法
// 参数一:用obj对象调用该方法
// 参数二:调用方法的传递的参数(如果没有就不写)
// 返回值:方法的返回值(如果没有就不写)
//1.获取class对象
Class clazz = Class.forName("com.aaa.Student");
//2.获取里面的Method对象 function4
Method method = clazz.getMethod("function4", String.class);
//3.运行function4方法就可以了
//3.1创建一个Student对象,当做方法的调用者
Constructor con = clazz.getConstructor();
Student student = (Student)con.newInstance();
//3.2运行方法
Object result = method.invoke(student, "zhangsan");
//4.打印一下返回值
System.out.println(result);
}
}
3、反射操作获取注解:
public class TestAnnotation {
public static void main(String[] args){
try {
//获取Student的Class对象
Class stuClass = Class.forName("pojos.Student");
//说明一下,这里形参不能写成Integer.class,应写为int.class
Method stuMethod = stuClass.getMethod("study",int.class);
if(stuMethod.isAnnotationPresent(CherryAnnotation.class)){
System.out.println("Student类上配置了CherryAnnotation注解!");
//获取该元素上指定类型的注解
CherryAnnotation cherryAnnotation = stuMethod.getAnnotation(CherryAnnotation.class);
System.out.println("name: " + cherryAnnotation.name() + ", age: " + cherryAnnotation.age()
+ ", score: " + cherryAnnotation.score()[0]);
}else{
System.out.println("Student类上没有配置CherryAnnotation注解!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
注意:
如果我们要获得的注解是配置在方法上的,那么我们要从Method对象上获取;如果是配置在属性上,就需要从该属性对应的Field对象上去获取,如果是配置在类型上,需要从Class对象上去获取。总之在谁身上,就从谁身上去获取!
isAnnotationPresent(Class<? extends Annotation> annotationClass)方法是专门判断该元素上是否配置有某个指定的注解;
getAnnotation(Class<A> annotationClass)方法是获取该元素上指定的注解。之后再调用该注解的注解类型元素方法就可以获得配置时的值数据;
反射对象上还有一个方法getAnnotations(),该方法可以获得该对象身上配置的所有的注解。它会返回给我们一个注解数组,需要注意的是该数组的类型是Annotation类型,这个Annotation是一个来自于java.lang.annotation包的接口。