Java反射和注解的使用

来源:互联网 发布:传统软件强调系统性 编辑:程序博客网 时间:2024/04/28 19:58

反射的使用:


相关包:java.lang.reflect,java.lang.Class


利用反射调用其它类的方法:


首先获取相关类的实例化Class,


方法为:


1.利用Class类的静态方法forName(String className); 


2.利用.class的方式获得,对于基本数据的封装类型可以用.TYPE获取,如int.class与Inter.TYPE时等效的。


3.对于对象可以对象.getClass()来获取Class实例。


通过这个Class对象调用getMethod(String name, Class<?>... parameterTypes)方法获取Method实例(第二个可变参数为对应方法的参数类

型)。用Class对象调用newInstance()方法创建一个新的Object实例,通过方法对象的invoke(Object obj, Object... args)

方法调用该Class对象的相关方法。(第一个参数为该Class对象的实例化的Object对象,第二个参数为即将被调用方法的参数)。


代码如下:

public class reflectClass{public static final void main(String args){}public void method1(){System.out.println("这是不带参的方法1");}public void method1(String param){System.out.println("这是带参的方法1,参数为:"+param);}}import java.io.*;import java.lang.reflect.Method;public class reflectTest{public static final void main(String[] args){try {Scanner sca=new Scanner(System.in);String className,methodName;System.out.print("请输入类名:");className=sca.next();System.out.print("\n请输入方法名:");className=sca.next();Class<?> cn=Class.forName(className);Class<?> cs=String.class;Method method=cn.getMethod(methodName,cs);Object object=cn.newInstance();method.invoke(object,"这是参数");method=cn.getMethod(methodName);method.invoke(object);}} catch (Exception e) {e.printStackTrace();}}}


通过反射来获取指定类的信息:


c.getSuperclass().getCanonicalName():获取其Class类型的父类然后通过getCanonicalName()规范化输出字符串。


Modifier.toString(c.getModifiers()):获取其修饰符然后通过解码类Modifier的toString方法将其转换成字符串输出。


其它获取信息的方法见api文档java.lang.Class中的方法。



注解的使用:


相关包:java.lang.annotation


注解类型:


@Documented:某一类型的注解将通过javadoc和类似的默认工具进行文档化,即该注解会出现在文档中。


@Retention:注释类型要保留多久,若声明注释时不存在Retention,默认为RetentionPolicy.CLASS。value包括:RetentionPolicy.CLASS(将注释记录在类文件中),RetentionPolicy.RUNTIME(将注释记录在类文件中,也会在运行时VM中保留,故可以反射性地读取),RetentionPolicy.SOURCE(会被编译器丢弃)。


@Target:注释类型所适用地地方,如方法或类型前。value包括:TYPE(类,接口(包括注释类型),枚举声明),FILED(字段声明(包括枚举常量)),METHOD,PARAMETER(参数声明),CONSTRUCTOR(构造方法声明),LOCAL_VARIABLE(局部变量声明),ANNOTATION_TYPE(注释类型声明),PACKAGE(包声明)。


通过注解和反射来调用其它类的方法:


首先创建一个类用来存放被调用的方法,一个类用来定义注解,和一个类用来利用注解和反射来调用类一的方法。在第一个类的每个方法前添加类二中定义的注解并赋值,在类三通过反射来创建类一实例,获取类一的所有方法,然后获取类二中的注解实例,通过注解中的值循环匹配,符合则调用该方法。代码如下:


类一:

public class Test3_1 {private String str1;private String str2;@Test3_2(value="fun1" //给注解赋值)public void fun1(){System.out.println("这是方法1");}@Test3_2(value="fun2")public void fun2(){System.out.println("这是方法2");}@Test3_2(value="fun3")public void fun3(){System.out.println("这是方法3");}}


类二(注解类型):

import static java.lang.annotation.ElementType.TYPE;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;@Documented@Retention(RUNTIME)@Target({TYPE,FIELD,METHOD})public @interface Test3_2 {String value() default "value";//赋初始值}



类三:

import java.lang.annotation.Annotation;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Scanner;import test3.Test3_2;public class Test3_3 {public static final void main(String[] args){String str;Scanner inp=new Scanner(System.in);while(true){str=inp.nextLine();try {Class c=Class.forName("test3.Test3_1");Method[] ms=c.getDeclaredMethods();for(Method m:ms){Annotation a=m.getAnnotation(Test3_2.class);if(str.equals(((Test3_2)a).value())){try {m.invoke(c.newInstance());} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}}} catch (ClassNotFoundException e) {e.printStackTrace();}}}}

重复注解的使用:


首先需要创建一个注解和一个用来存放第一个注解的注解

import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Documented;import java.lang.annotation.Repeatable;import java.lang.annotation.Retention;import java.lang.annotation.Target;@Documented@Retention(RUNTIME)@Target(METHOD)@Repeatable(Schedules.class)public @interface Schedule {int value();}

import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;@Documented@Retention(RUNTIME)@Target(METHOD)public @interface Schedules {Schedule[] value();}


然后就可以使用重复使用Schedule注解

public class UseRepeatableAnnotation {@Schedule(1)@Schedule(2)public void fun1() {System.err.println("这是第一个函数!");}public void fun2() {System.err.println("这是第二个函数!");}@Schedule(2)public void fun3() {System.err.println("这是第三个函数!");}public void fun4() {System.err.println("这是第四个函数!");}}

解析重复注解

import java.lang.annotation.Annotation;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import 重复注解.Schedule;public class ParseAnnotation {public static void main(String[] args) {try {Class c=Class.forName("test.UseRepeatableAnnotation");Method[] methods=c.getDeclaredMethods();for(Method m:methods){//获取每个方法的注解,如果是重复注解,则获取存储重复注解的注解Annotation[] as=m.getAnnotations();//获取方法的注解System.out.println("\n\n方法名:"+m.getName());for(Annotation a:as){System.out.println("  该方法的所有注解:"+a.toString());System.out.println("       注解类型信息:"+a.annotationType());}System.out.println("*******************");//获取某个重复注解的方法Annotation[] ass=m.getAnnotationsByType(Schedule.class);//根据注解类型获取方法的重复注解System.out.println("方法名:"+m.getName());for(Annotation a:ass){System.out.println("  该方法的所有注解:"+a.toString());System.out.println("       注解类型信息:"+a.annotationType());//当方法的注解的值为1时,调用该方法if(((Schedule)a).value()==2)//获取注解的值((Schedule)a).value()m.invoke(c.newInstance());}}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}



原创粉丝点击