我们可以使用注释的主要领域是什么?该特性是基于XML的配置的替代品吗?


当前回答

Java的注释有多种应用程序。首先,它们可能被编译器(或编译器扩展)使用。以Override注释为例:

class Foo {

    @Override public boolean equals(Object other) {
        return ...;
    }
}

它实际上内置于Java JDK中。如果某个方法被标记为错误,编译器将发出错误信号,该方法不会覆盖从基类继承的方法。这个注释可能有助于避免常见的错误,即你实际上打算覆盖一个方法,但由于方法中给出的签名与被覆盖方法的签名不匹配而失败:

class Foo {

    @Override public boolean equals(Foo other) {  // Compiler signals an error for this one
        return ...;
    }
}

从JDK7开始,任何类型都允许标注。这个特性现在可以用于编译器注释,比如NotNull,比如:

public void processSomething(@NotNull String text) {
    ...
}

这允许编译器警告你不适当/未检查的变量和空值的使用。

另一个更高级的注释应用程序涉及运行时的反射和注释处理。当您说注释是“基于XML的配置的替代品”时,这就是您所想到的(我认为)。例如,各种框架和JCP标准(持久性、依赖项注入等等)都使用这种注释处理,以便提供必要的元数据和配置信息。

其他回答

注释可以在哪里使用

注释可以应用于声明:类、字段、方法和其他程序元素的声明。在声明上使用时,根据约定,每个注释通常出现在自己的行上。

Java SE 8 Update:注释也可以应用于类型的使用。下面是一些例子:

类实例创建表达式: @Interned MyObject(); 类型转换: myString =(@非空字符串)str; 实现条款: 类UnmodifiableList实现 @Readonly List<@Readonly T>{…} 抛出的异常声明: void monitorTemperature()抛出 @临界温度异常{…}

注释是元对象,可以用来描述其他元对象。元对象包括类、字段和方法。向一个对象请求它的元对象(例如anObj.getClass())被称为内省。内省可以更进一步,我们可以问元对象它的注释是什么(例如aClass.getAnnotations)。内省和注释属于所谓的反射和元编程。

注释需要以一种或另一种方式进行解释才能有用。注释可以在开发时由IDE或编译器解释,也可以在运行时由框架解释。

注释处理是一种非常强大的机制,可以以许多不同的方式使用:

描述一个元素的约束或用法:例如@Deprecated, @Override,或@NotNull 来描述一个元素的“性质”,例如@Entity, @TestCase, @WebService 来描述元素的行为:@Statefull, @Transaction 来描述如何处理元素:@Column, @XmlElement

在所有情况下,注释都用于描述元素并阐明其含义。

在JDK5之前,现在用注释表示的信息需要存储在其他地方,并且经常使用XML文件。但是使用注释更方便,因为它们属于Java代码本身,因此比XML更容易操作。

注释的使用:

文档,例如XDoclet 编译 IDE 测试框架,例如JUnit IoC容器,例如Spring 序列化,例如XML 面向方面编程(AOP),例如Spring AOP 应用服务器,例如EJB容器、Web服务 对象-关系映射(ORM),例如Hibernate、JPA 还有更多……

...比如Lombok项目,它使用注释来定义如何生成equals或hashCode方法。

Java中的注释提供了一种描述类、字段和方法的方法。本质上,它们是添加到Java源文件中的一种元数据形式,它们不能直接影响程序的语义。但是,注释可以在运行时使用反射读取&这个过程被称为内省。然后,它可以用来修改类、字段或方法。

这个特性,经常被库和sdk (hibernate, JUnit, Spring Framework)利用来简化或减少程序员在使用这些库或sdk时需要做的代码量。因此,可以公平地说,注释和反射在Java中是齐头并进的。

我们还将注释的可用性限制在编译时或运行时。下面是一个创建自定义注释的简单示例

Driver.java

package io.hamzeen;

import java.lang.annotation.Annotation;

public class Driver {

    public static void main(String[] args) {
        Class<TestAlpha> obj = TestAlpha.class;
        if (obj.isAnnotationPresent(IssueInfo.class)) {

            Annotation annotation = obj.getAnnotation(IssueInfo.class);
            IssueInfo testerInfo = (IssueInfo) annotation;

            System.out.printf("%nType: %s", testerInfo.type());
            System.out.printf("%nReporter: %s", testerInfo.reporter());
            System.out.printf("%nCreated On: %s%n%n",
                    testerInfo.created());
        }
    }
}

TestAlpha.java

package io.hamzeen;

import io.hamzeen.IssueInfo;
import io.hamzeen.IssueInfo.Type;

@IssueInfo(type = Type.IMPROVEMENT, reporter = "Hamzeen. H.")
public class TestAlpha {

}

IssueInfo.java

package io.hamzeen;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Hamzeen. H.
 * @created 10/01/2015
 * 
 * IssueInfo annotation definition
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IssueInfo {

    public enum Type {
        BUG, IMPROVEMENT, FEATURE
    }

    Type type() default Type.BUG;

    String reporter() default "Vimesh";

    String created() default "10/01/2015";
}

像Hibernate这样的框架需要大量的配置/映射,大量使用annotation。

看一看Hibernate注解

Java的注释有多种应用程序。首先,它们可能被编译器(或编译器扩展)使用。以Override注释为例:

class Foo {

    @Override public boolean equals(Object other) {
        return ...;
    }
}

它实际上内置于Java JDK中。如果某个方法被标记为错误,编译器将发出错误信号,该方法不会覆盖从基类继承的方法。这个注释可能有助于避免常见的错误,即你实际上打算覆盖一个方法,但由于方法中给出的签名与被覆盖方法的签名不匹配而失败:

class Foo {

    @Override public boolean equals(Foo other) {  // Compiler signals an error for this one
        return ...;
    }
}

从JDK7开始,任何类型都允许标注。这个特性现在可以用于编译器注释,比如NotNull,比如:

public void processSomething(@NotNull String text) {
    ...
}

这允许编译器警告你不适当/未检查的变量和空值的使用。

另一个更高级的注释应用程序涉及运行时的反射和注释处理。当您说注释是“基于XML的配置的替代品”时,这就是您所想到的(我认为)。例如,各种框架和JCP标准(持久性、依赖项注入等等)都使用这种注释处理,以便提供必要的元数据和配置信息。