
本文简要概述了Java批注中的相关知识点. 如果有任何不清楚或不正确的描述java中注释编译时,我希望每个人都可以纠正我. 谢谢: )
我们都知道在Java代码中使用注释是为了向将来阅读此代码的人解释一些事情. 注释是注释的升级版本,可以向编译器,虚拟机等解释某些内容. 例如,我们非常熟悉@Override是元注释,它的作用是告诉编译器注释方法是重写父类方法,以便编译器将检查父类是否存在此方法,并且此方法与父类的签名相同.
也就是说,注释用于描述Java代码,可以由编译器进行解析,并且注释处理工具还可以在运行时解析注释. 当我们或其他人稍后阅读此代码时,我们使用Java源文件中的注释来更好地理解它. Javadoc工具可以解析我们添加到源代码中的类,方法,变量等的描述信息,并且只要我们为该类,方法添加的描述信息就可以基于这些描述信息自动生成HTML文档. 等等符合Javadoc所需的语法,我们可以使用Javadoc工具根据我们的描述信息自动生成帮助文档. 注释比Java注释和Javadoc强大得多. 两者之间的重要区别是Java注释和Javadoc描述仅在编译时停止,而注释可以一直运行到运行时.
我们知道,使用“ transient”关键字可以告诉编译器该域不可序列化. 与使用“ transient”之类的关键字修改属性相比,注释为我们提供了一种更通用的方法来添加类/方法/属性/变量的描述信息,这些描述信息适用于开发人员,自动化工具,Java编译器和浏览器. Java运行时非常有意义,这意味着它们都可以“读取”注释信息. “ transient”关键字是修饰语,而注释也是修饰语. 除了传递信息之外,我们还可以使用注释来生成代码. 我们可以使用注释,然后让注释分析工具解析它们以生成一些“模板化”代码. Hibernate,Spring和Axis等框架大量使用注释,以避免重复工作.
元注释是用于描述注释的注释. 例如,在以下代码中,我们使用“ @Target”元注释来说明MethodInfo注释只能用于注释方法:
@Target(ElementType.METHOD)public @interface MethodInfo {
...
}
这是一些特定的元注释.
当@Documented元注释描述注释类型时,无论在何处使用此注释,Javadoc工具都将对其进行记录. 让我们看一下它的定义:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
从上面的代码中我们可以看到,定义注释使用@interface关键字,就像定义类时使用class关键字,定义接口时使用interface关键字一样. 注释也是一种类型. 此元注释用@Documented修饰,表示也将进行记录. @Retention元注RetentionPolicy.RUNTIME的值表示@Documented批注可以保留到运行时; @Target元注ElementType.ANNOTATION_TYPE的值表示@Documented注释只能用于描述注释类型.
表示修改后的注释类型是自动继承的. 具体说明如下: 如果注释类型被继承的元注释修改,则当用户在类声明中查询注释类型时,如果该注释类型不包含在类声明中,它将自动在父类中类的类查询相应的注释类型,将重复此过程,直到找到注释类型或搜索后未找到Object类. 此元注释的定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
我们可以看到此元注释类型由@Documented进行注释,该注释可以保留到运行时,并且只能用于描述注释类型.
我们已经在上面看到了此元注释,它指示何时保留注释类型. 例如,以下代码指示在运行时之前将保留Developer批注:
@Retention(RetentionPolicy.RUNTIME)
public @interface Developer {
String value();
}
@Retention元注释的定义如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
当我们使用@Retention时,其后面方括号中的内容表示他的价值. 从上面的定义中,我们可以看到值的类型是RetentionPolicy,它是一种枚举类型. 它可以采用以下值:
此元注释描述了修改后的注释的应用范围,即修改后的注释可用于注释哪些程序元素. 其定义如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
从上面的定义中,我们可以看到它也将一直保留到运行时,其值的类型为ElementType [](一个数组,意味着可以指定多个值),ElementType是一个枚举类型,它可以采用以下值:
Java本身内建了一些注解,下面我们来介绍一下我们在日常开发中比较常见的注解:@Override、@Deprecated、@SuppressWarnings。相信我们大家或多或少都使用过这三个注解,下面我们一起再重新认识一下它们。

让我们首先看一下该注释类型的定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
根据其定义,我们可以看到此注释可用于修改方法,并且仅在编译时有效java中注释编译时,并且在已编译的类文件中不再存在. 我们所有人都熟悉此批注的效果,即告诉编译器,修改后的方法与重写的父类中的签名方法相同. 编译器将对此进行检查. 如果发现父类中不存在此方法,或者方法或现有方法签名不同,则会报告错误.
此注释的定义如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
根据其定义,我们知道它将被记录下来,可以保留到运行时,并且可以修改构造函数,属性,局部变量,方法,包,参数和类型. 此批注的目的是告诉编译器装饰的程序元素已被“弃用”,不再建议用户使用.
我们也经常使用此评论. 我们先来看一下它的定义:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
它可以修改的程序元素包括类型,属性,方法,参数,构造函数和局部变量. 它们只能在源代码中生存,并采用值String []. 它的作用是告诉编译器忽略指定的警告消息. 可以采用的值如下:
使用此注释的示例如下:
@SuppressWarning(value={"deprecation", "unchecked"})
public void myMethos() {
...
}

通过使用以上注释,我们告诉编译器由于使用废弃的类或方法或未经检查的转换而忽略了myMethod方法生成的警告.
我们可以创建自己的注释类型并使用它. 请参见以下示例:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MethodInfo {
String author() default "absfree";
String date();
int version() default 1;
}
自定义注释时,我们需要了解以下几点:
让我们看一下上面提到的注释类型@SuppressWarnings的定义. 此注释类型由系统为我们定义. 其定义如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
我们可以看到它仅定义了一个注释方法value(),其返回值类型为String [],并且未指定默认返回值. 我们用于@SuppressWarnings批注的语法如下:
@SuppressWarnings(value={"value1", "value2", ...})
也就是说,可以通过在注释类型名称后面的括号中为每个注释方法指定返回值来使用此注释. 让我们看一下如何使用自定义注释类型@MethodInfo:
public class AnnotationTest {
@MethodInfo(author="absfree", date="20160410")
public static void main(String[] args) {
System.out.println("Using custom annotation...");
}
}
现在问题来了,我们使用的自定义注释对编译器或虚拟机有意义吗(编译器或虚拟机可以理解吗)?显然,如果我们什么也不做,则编译器或虚拟机将无法读取我们的自定义批注. 让我们介绍一下以释的分析,以便编译器或虚拟机可以读取我们的自定义注释.

编译时注释是指@Retention的值为CLASS的注释. 对于此类注释的分析,我们只需要做以下两件事:
然后,编译器将在编译时自动查找从AbstractProcessor继承的所有类,然后调用其处理方法. 因此,只要我们做以上两件事,编译器就会主动解析我们的编译时注释. 现在,我们将上面定义的MethodInfo的保留时间更改为CLASS,并可以根据以下代码对其进行解析:
@SupportedAnnotationTypes({ "com.custom.customannotation.MethodInfo" })
public class MethodInfoProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
HashMap<String, String> map = new HashMap<String, String>();
for (TypeElement typeElement : annotations) {
for (Element element : env.getElementsAnnotatedWith(typeElement)) {
MethodInfo methodInfo = element.getAnnotation(MethodInfo.class);
map.put(element.getEnclosingElement().toString(), methodInfo.author());
}
}
return false;
}
}
@SupportedAnnotationTypes注释描述了处理器要解析的注释的名称. process函数的注释参数指示要处理的注释集,而env指示当前或先前运行的环境. 处理函数的返回值指示此处理器是否接受注释中的注释.
有关更详细的介绍,请参考使用APT技术的Android在编译时生成代码
首先,我们将MethodInfo批注类型中的Retention的值更改回原始的RUNTIME. 接下来,我们介绍如何通过反射机制在运行时解析自定义注释类型.
java.lang.reflect包中有一个AnnotatedElement接口. 该接口定义了几种获取注释信息的方法:
//返回该程序元素的指定类型的注解,若不存在这个类型的注解则返回null
T getAnnotation(Class annotationClass)
//返回修饰该程序元素的所有注解
Annotation[] getAnnotations()
//返回直接修饰该元素的所有注解
Annotation[] getDeclaredAnnotations()
//当该程序元素被指定类型注解修饰时,返回true,否则返回false
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
用于解析上述自定义注释MethodInfo的相关示例代码如下(AnnotationParser.java):
public class AnnotationParser {
public static void main(String[] args) {
try {
Class cls = AnnotationTest.class;
for (Method method : cls.getMethods()) {
MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
if (methodInfo != null) {
System.out.println("method name:" + method.getName());
System.out.println("method author:" + methodInfo.author());
System.out.println("method date:" + methodInfo.date());
System.out.println("method version:" + methodInfo.version());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过运行上面的代码,我们可以获得以下输出:
这表明我们已经成功解析了自定义注释. 关于注释,我们需要清楚一点,作为描述代码本身的一种元数据,注释是一种“被动”信息. 换句话说,必须先由编译器或虚拟机“主动”解析它,然后才能发挥作用. Java文档公共技术点Java注释的Java注释
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-237693-1.html
抗日得时候多少人抵制日货又能怎么样
和美海军这样的对手玩比和毛子玩会有意义
上次来过