注解入门
注解是JDK 1.5增加的。
类名把Test放在前面,可不可以啊?不可以,因为类名往往是名词,只有方法才是动词,放在前面就是动词,测试注解,放在后面就是注解的测试。这是有说法的,一个很小的习惯不能不提。类名属性名、变量名都是名词。或者形容词加名词,方法名是动词或是动词加名词。要养成良好的编码习惯。
如果想调用一些过时的API,但又不想编译器警告,可以在自己写的调用此API的方法外部,方法代码的上一行写上@SuppressWarnings(),括号中加入所调用的过时API的API名的字符串。
注解就是告诉开发工具或者告诉编译器说你要干什么什么事情,不要干什么什么事情。上面的注解是javaSDK内部自带的一个注解。一个注解就是一个类。我们在这里用了一个注解就相当于创建了这个类的示例对象。
既然javasdk自带忽略过时的注解,自然也有标注过时的注解,用于标注过时的注解是@Deprecated
javajdk自带的注解还有@Override 重写父类方法。
注解相当于一种标记,加上注解就等于打上了某种标记,没加,则等于没有某种标记,加上以后,javac编译器,开发工具和其他程序可以用反射来了解你的类以及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包、类,字段,方法,方法的参数以及局部变量上。
自定义注解
注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得现有开发好这个类。
如何写注解类呢?
1.先就像接口一样写就可以,只不过在接口名词interface前面加一个@符号,这是类A。
2.还要有应用上面注解类的类B
3.还要有个通过反射能够检查出类A是否被应用,以及应用后如何操作的类C。
对于 类A,我们可以作如下初始化的代码:
public @interface SeanAnnotation {
}
这之后,我们还可以为其再加上一个注解,是为注解的注解,下面加入的注解,是为我们自定义的注解服务的不是为普通类服务的。这种为注解类添加的注解,称之为元注解。
@Retention(RetentionPolicy.SOURCE)
public @interface SeanAnnotation {
接下来我们就解释解释这个元注解Retention。这个注解呢,还保留在class文件中,为什么能保留在class文件中呢?因为我在设计这个注解的时候,我在这上面加了一个说明,说什么呢?说哥们,你一直保留到运行期间啊。当我在java元程序身上加了一个注解,这个源程序接着就要被javac去编译吧,javac把源文件编译成什么?编成class,它编译成class的时候,它可能会把源程序里面的一些注解给去掉。我要处理这个源文件吧,处理的时候,哎,这个没用了,不要了。好,你拿到class文件的时候注解还有没有啊,就没有了。这是一种可能。假设javac编译器,把这个注解留在了class文件里面,接着我们的程序在用这个class的时候,是不是用类加载器把class文件调到内存里面来啊,class文件里面的东西不是字节码,只有把class文件里面的东西加载到内存里面来了。由类加载器加载。类加载器加载完了以后,在内存中的东西才是字节码。
所以说,一个注解的生命周期有三个阶段,java源文件,class文件,内存中的字节码。
分别对应RetentionPolicy.SOURCE,RetentionPolicy.CLASS, RetentionPolicy.RUNTIME.
默认是在RetentionPolicy.CLASS。
我们还可以给SeanAnnotation这个注解再添加一个注解@Target,表示这个注解的作用域是哪一块?是类、是方法,还是字段?
@Retention(RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SeanAnnotation {
}
其中ElementType.TYPE表示作用域是类、枚举,接口等等。
对于类B,我们可以作如下初始化的代码:
@SeanAnnotation
public class AnnotationTest {
}
对于 类C,我们可以作如下初始化的代码:
//判断AnnotationTest类存不存在SeanAnnotation这个Annotation
if(AnnotationTest.class.isAnnotationPresent(SeanAnnotation.class)){
//既然有,就先得到这个注解的实例对象,这个实例对象是在应用的时候产生的
SeanAnnotation seanAnnotation = AnnotationTest.class.getAnnotation(SeanAnnotation.class);
}
为注解增加基本属性
注解功能之所以这么强大,就是因为它有属性。属性有什么作用,我们来看一看怎么样为注解增加属性。
这个注解很像接口,那么属性就很像方法。
@Retention(RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SeanAnnotation {
String color();
}
@SeanAnnotation(color = "red")
public class AnnotationTest {
public void cheakAnn(){
//判断AnnotationTest类存不存在SeanAnnotation这个Annotation
if(AnnotationTest.class.isAnnotationPresent(SeanAnnotation.class)){
//既然有,就先得到这个注解的实例对象,这个实例对象是在应用的时候产生的
SeanAnnotation seanAnnotation = AnnotationTest.class.getAnnotation(SeanAnnotation.class);
String color = seanAnnotation.color();
}
}
}
这就是为注解添加属性。
那么@SuppressWarnings("deprecation")是不是属性呢?是属性,只不过很特殊,特殊到可以把属性名加等号省略。这个属性就是String value(); 如果只有一个value属性需要设置,那么就可以不写value属性名加等号了。当然如果不是只有一个属性,还可以为某一个属性设置默认值。
@Retention(RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SeanAnnotation {
String color() default "blue";
String value();
}
当然也可以添加数组、枚举、注解属性等。