您的位置:首页 > 编程语言 > Java开发

Java之反射和注解

2017-10-31 18:21 190 查看
反射的使用:
相关包: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
4000
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 block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 注解 反射