Java注解之基本语法
不管是做后端开发还是前端开发,在实际开发中都会涉及到注解这个知识点。今天主要针对Java的注解进行讲解,考虑到篇幅问题,这篇主要分享Java注解的基本语法,以及几个简单的示例。
为什么要学习注解呢?
现在不管是后端工程师还是前端工程师,都会使用到各种各样的框架,在每一个框架里面,都会大量使用到注解,为了能够读懂框架源码,我们必须会使用注解;使用注解也可以使我们的代码变得简洁。
第一部分:JDK自带注解
在JDK中有大量的注解,下面通过一个简单的示例说明。
1. 创建一个Offer接口,定义两个方法,如下:
package com.study.annotation.default_annotation;
/**
* <p>Title: Offer</p >
* <p>Description: offer interface </p >
* <p>Company: http://www.yinjiedu.com</p >
* <p>Project: concurrency</p >
*
* @author: qiwei
* @Date: 2019/10/10 21:58
* @Version: 1.0
*/
public interface Offer {
String findName();
@Deprecated
String obtainIdfa();
}
在上面我们使用了第一个注解@Deprecated,这个注解使用在此处的原因是obtainIdfa()方法已经遗弃,但是为了不影响已经使用了该方法的类,所以将该方法添加注解说明。
该注解的定义如下:
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* A program element annotated @Deprecated is one that programmers
* are discouraged from using, typically because it is dangerous,
* or because a better alternative exists. Compilers warn when a
* deprecated program element is used or overridden in non-deprecated code.
*
* @author Neal Gafter
* @since 1.5
* @jls 9.6.3.6 @Deprecated
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
现在这段代码可能看不懂,但是不要着急,等看完后面的知识点,回过头来再看这段代码,大家会觉得特别简单。
2. 实现Offer接口,代码如下:
package com.study.annotation.default_annotation;
/**
* <p>Title: OfferImp</p >
* <p>Description: offer接口实现</p >
* <p>Company: http://www.yinjiedu.com</p >
* <p>Project: concurrency</p >
*
* @author: qiwei
* @Date: 2019/10/10 21:59
* @Version: 1.0
*/
public class OfferImp implements Offer {
@Override
public String findName() {
return null;
}
@Override
public String obtainIdfa() {
return null;
}
}
上面使用到了@Override注解,相信Java开发人员对这个注解不会陌生,该注解表明方法是一个覆盖方法。该注解定义如下:
package java.lang;
import java.lang.annotation.*;
/**
* Indicates that a method declaration is intended to override a
* method declaration in a supertype. If a method is annotated with
* this annotation type compilers are required to generate an error
* message unless at least one of the following conditions hold:
*
* <ul><li>
* The method does override or implement a method declared in a
* supertype.
* </li><li>
* The method has a signature that is override-equivalent to that of
* any public method declared in {@linkplain Object}.
* </li></ul>
*
* @author Peter von der Ahé
* @author Joshua Bloch
* @jls 9.6.1.4 @Override
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
当然,在学习完这节内容我们再看该注解的定义。
我们在Offer接口定义中,对obtainIdfa()使用了@Deprecated注解,那么怎么模拟查看该注解的实际效果了,我们看下面代码(该段代码要截图展示,不然看不出实际效果):
我们看到在实际使用obtainIdfa()方法的时候,该方法会有横线划掉的标志。那么我们怎么不让编译器检查到这个警告了?这里我们又要使用到JDK提供给我们的一个注解,如下:
可以看到obtainIdfa()方法的警告没有了。
第二部分:注解基本语法
1. 注解分类
注解分为编译时注解、运行时注解、源码注解
编译时注解:注解在源码和.class文件中都存在(上面使用到的几个注解都属于编译时注解);
运行时注解:在运行时也会起作用,运行时注解可以影响到程序的实际逻辑;
源码注解:只在源码中存在,代码编译成.class文件之后,注解就不存在了。
注意:除过上面提到的三类注解之外,还有一个元注解,元注解使给注解进行注解。
2. 自定义注解
我们先看一个已有注解的定义语法,通过分析具体语法,定义出自己的注解,代码如下:
1. 注解定义关键字
@interface关键字表明,定义的既不是类也不是接口,而是一个注解,所以定义注解第一步就是使用@interface。
2. 注解成员
在上面注解定义的成员为:
String value() default "";
成员定义:成员没有参数、没有异常进行定义;可以使用default给成员赋默认值;
成员类型:成员类型使受限制的,注解合法的成员类型为原始类型、String、Class、Annotation、Enumeration;
约定:如果注解只有一个成员,我们约定该成员命名为value,在使用的时候,可以省略成员名和赋值号(=)。
注意:注解可以没有成员,没有成员的注解我们称为标识注解。
3. 元注解
在上面注解里面的元注解为:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
(1)@Target({ElementType.METHOD, ElementType.TYPE})元注解定义注解的作用域,注解作用域我们查看源码可以看到有如下几类:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
每一个作用域都有注释,这里就不多做介绍。
(2)@Retention(RetentionPolicy.RUNTIME)元注解定义注解的生命周期,通过查看源码我们可以看到声明周期有如下几类:
package java.lang.annotation;
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
每一个生命周期定义都有详细的注释说明,这里不多赘述。
(3) @Inherited是一个标志性的元注解,它表明允许子类继承;
(4) @Documented表明生成Java的doc文档时会包含注解的信息。
第三部分:自定义注解
根据上面的语法,我们自定义一个注解,并且实际使用它,代码如下:
package com.study.annotation.user_defined;
import java.lang.annotation.*;
/**
* <p>Title: Util</p >
* <p>Description: 自定义注解</p >
* <p>Company: http://www.yinjiedu.com</p >
* <p>Project: concurrency</p >
*
* @author: qiwei
* @Date: 2019/10/10 23:30
* @Version: 1.0
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Util {
String desc();
String auth() default "WEIQI";
String dateTime();
}
这里定一个工具类描述性注解,成员包括描述、作者、时间信息。
第四部分:使用自定义注解
我们使用上面自定义注解,代码如下:
package com.study.annotation.user_defined;
import org.springframework.stereotype.Component;
/**
* <p>Title: CommonParameter</p >
* <p>Description: common parameter</p >
* <p>Company: http://www.yinjiedu.com</p >
* <p>Project: concurrency</p >
*
* @author: qiwei
* @Date: 2019/10/10 23:36
* @Version: 1.0
*/
@Component
@Util(desc = "公共参数定义", dateTime = "2019-10-10")
public class CommonParameter {
public final static String SUCCESS_CODE = "200";
}
通过上述例子可以看到,注解使用了default关键字定义了默认值之后,在使用注解的时候可以不用显示的处理。
关于注解的基本语法就介绍这么多,相信大家读到这里,对JDK自带注解的阅读都没有一点问题。有关注解的高级用法,会再出一篇文章来分享。
思考:注解的高级用法怎么使用,主要用在哪里?
提示:注解的高级用法要结合Java的反射机制来做,在平时工作中使用到的第三方注解,都使用到这方面的只是,大家可以自己实现一个简单的例子试试。
了解实时文章信息,请关注微信公众号《编程之艺术》