天天看点

java import自定义类_java自定义注解类

v一、前言

今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下。

v二、代码示例

java import自定义类_java自定义注解类

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;importjava.lang.reflect.Field;

//自定义注解类

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation {

String name() default "hjzgg";

}public classMain {publicMain(Class cls) {

Field[] fields=cls.getDeclaredFields();

TestAnnotation obj= null;try{

obj= (TestAnnotation)cls.getConstructors()[0].newInstance(this);//获取内部类对象

}catch(Exception e) {

e.printStackTrace();

}for(Field field : fields) {

System.out.println(field.getName()+ " " +field.getType().getName());if(!field.getName().equals("this$0")) {

MyAnnotation annotation= field.getAnnotation(MyAnnotation.class);//获取注解类

String name=annotation.name();

field.setAccessible(true);try{switch(name) {case "hjzgg":switch(field.getType().getName()) {case "int":case "java.lang.Integer":

field.set(obj,555);break;case "java.lang.String":

field.set(obj,"hehe");break;

}break;case "lxkdd":switch(field.getType().getName()) {case "int":case "java.lang.Integer":

field.set(obj,555);break;case "java.lang.String":

field.set(obj,"hehe");break;

}break;default:break;

}

}catch(Exception e) {

e.printStackTrace();

}

}

}

System.out.println(obj);

}public static void main(String[] args) throwsInstantiationException, IllegalAccessException {new Main(TestAnnotation.class);

}classTestAnnotation{publicTestAnnotation(){}

@MyAnnotation(name="lxkdd")private intx;

@MyAnnotationprivateString y;public intgetX() {returnx;

}public void setX(intx) {this.x =x;

}publicString getY() {returny;

}public voidsetY(String y) {this.y =y;

}

@OverridepublicString toString() {return "x: " + x + ", y: " +y;

}

}

}

java import自定义类_java自定义注解类

v三、代码分析

v  1.如何编写自定义注解

public @interfaceMyAnnotation {

String value()default "hahaha";

}

感觉等价于

java import自定义类_java自定义注解类

public class MyAnnotation extendsjava.lang.annotation.Annotation{private String value = "hahaha";public voidsetValue(String value){this.value =value;

}publicString getValue(){returnvalue;

}

}

java import自定义类_java自定义注解类

自定义注解类规则

@interface实际上是继承了java.lang.annotation.Annotation,所以定义annotation时不能继承其他annotation或interface. java.lang.annotation.Retention告诉编译器如何对待 Annotation,使用Retention时,需要提供java.lang.annotation.RetentionPolicy的枚举值.

public enumRetentionPolicy {

SOURCE,//编译器处理完Annotation后不存储在class中

CLASS, //编译器把Annotation存储在class中,这是默认值

RUNTIME //编译器把Annotation存储在class中,可以由虚拟机读取,反射需要

}

java.lang.annotation.Target告诉编译器Annotation使用在哪些地方,使用需要指定java.lang.annotation.ElementType的枚举值.

java import自定义类_java自定义注解类

public enumElementType {

TYPE,//指定适用点为 class, interface, enum

FIELD, //指定适用点为 field

METHOD, //指定适用点为 method

PARAMETER, //指定适用点为 method 的 parameter

CONSTRUCTOR, //指定适用点为 constructor

LOCAL_VARIABLE, //指定使用点为 局部变量

ANNOTATION_TYPE, //指定适用点为 annotation 类型

PACKAGE //指定适用点为 package

}

java import自定义类_java自定义注解类

java.lang.annotation.Documented用于指定该Annotation是否可以写入javadoc中.

java.lang.annotation.Inherited用于指定该Annotation用于父类时是否能够被子类继承.

示例

java import自定义类_java自定义注解类

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;

@Documented//这个Annotation可以被写入javadoc

@Inherited //这个Annotation 可以被继承

@Target({ElementType.CONSTRUCTOR,ElementType.METHOD}) //表示这个Annotation只能用于注释 构造子和方法

@Retention(RetentionPolicy.CLASS) //表示这个Annotation存入class但vm不读取

public @interfaceMyAnnotation {

String value()default "hahaha";

}

java import自定义类_java自定义注解类

v  2.如何获取自定义注解

java.lang.reflect.AnnotatedElement接口提供了四个方法来访问Annotation

publicAnnotation getAnnotation(Class annotationType);publicAnnotation[] getAnnotations();publicAnnotation[] getDeclaredAnnotations();public boolean isAnnotationPresent(Class annotationType);

来自:http://blog.csdn.net/foamflower/article/details/5946451

Class、Constructor、Field、Method、Package等都实现了该接口,可以通过这些方法访问Annotation信息,前提是要访问的Annotation指定Retention为RUNTIME.

Java内置的annotation有Override Deprecated SuppressWarnings.

Override只用于方法,它指明注释的方法重写父类的方法,如果不是,则编译器报错.

Deprecated指明该方法不建议使用.

SuppressWarnings告诉编译器:我知道我的代码没问题.

v  3.this$0是什么意思?

java import自定义类_java自定义注解类

public class Outer {//this$0

public class FirstInner {//this$1

public class SecondInner {//this$2

public classThirdInner {

}

}

}

}

java import自定义类_java自定义注解类

说一个场景:当我们拿到了一个内部类的对象Inner,但是又想获取其对应的外部类Outer,那么就可以通过this$0来获取。this$0就是内部类所自动保留的一个指向所在外部类的引用。

java import自定义类_java自定义注解类

//通过工具获取到Inner实例对象

Outer.Inner inner = getInner();//获取内部类Inner的一个字段this$0信息//this$0特指该内部类所在的外部类的引用,不需要手动定义,编译时自动加上

Filed outerField = inner.getClass().getDeclaredField("this$0");//this$0是私有的,提升访问权限

outerField.setAccessible(true);//拿到该字段上的实例值

Outer outer = (Outer)outerField.get(inner);

java import自定义类_java自定义注解类

v  4.java如何反射内部类

Class> cls = Class.forName("package.OuterClass$InnerClass"); orClass> cls = OuterClass.InnerClass.class;

(1)OuterClass.InnerClass obj= (OuterClass.InnerClass)cls.getConstructors()[0].newInstance(new OuterClass());

(2)OuterClass.InnerClass obj= (OuterClass.InnerClass)cls.getConstructor(OuterClass.class).newInstance(new OuterClass());

由此可见,内部类的无参构造器在通过反射机制获取时,要指定其父类参数才可以获得,否则将报如下异常:

java.lang.NoSuchMethodException: com.hjzgg.OuterClass$InnerClass.()

at java.lang.Class.getConstructor0(Class.java:3082)

at java.lang.Class.getConstructor(Class.java:1825)