Java注解

原文链接:https://www.yiibai.com/article/detail/8350

Java注解用于为Java代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解可以用于这一目的。Java注解是从Java5开始添加到Java中。

1. 什么是注解

Java注解用于为Java代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。
Java注解通常用于以下目的:

  • 编译器指令
  • 编译时指令
  • 运行时指令

1.1. 编译指令

Java有3个内置的注解,你可以用它来发出指令到Java编译器。

这些注释后面详细文件中会解释。

1.2. 编译时指令

当创建建软件项目时,Java注释可以在编译时使用。构建过程包括生成的源代码,编译源文件,生成XML文件(例如部署描述符),包装编译代码和文件到一个JAR文件等。构建软件通常是通过像Apache Ant组织的Apache Maven的自动构建工具完成。构建工具可以扫描你的Java代码指定的注解并生成源代码或基于这些注解其他文件。

1.3. 运行时指令

通常情况下,Java注解中不存在于编译后的Java代码。这是可能的,但是,定义自己的注解是在运行时可用。这些注解然后可以通过Java反射访问,并用于发出指令到程序,或者一些第三方API。

2. 内置注解

Java有3个重要注解可用:

2.1. @Deprecated注解

它是用来注解过时的东西,如类或方法的注解; 如果使用的东西过时,编译器会通知应该使用的另一种方式。或IDE工具,像Eclipse,它也给显示出可视化通知。

文件:DeprecatedMethodDemo.java

package com.yiibai.tutorial.ann.builtin;

import java.util.Date;

public class DeprecatedMethodDemo {

   /**
    * @deprecated replaced by {@link #todo(String,Date)}
    */
   @Deprecated
   public void todoJob(String jobName) {
       System.out.println("Todo " + jobName);
   }

   public void todo(String jobName, Date atTime) {
       System.out.println("Todo " + jobName + " at " + atTime);
   }

   public void todoNothing() {
       System.out.println("Todo Nothing");
   }

   public static void main(String[] args) {

       DeprecatedMethodDemo obj = new DeprecatedMethodDemo();

       obj.todoJob("Java coding");

       obj.todoNothing();
   }
}

Java

如下图所示,Eclipse将通知:

Eclipse提示

2.2. @Override注解

@Override注解来覆盖超类方法在方法使用。如果这个方法不超匹配的方法,编译器就会提示一个错误。

要覆盖超类的方法而使用 @Override 注解不是必需的。如坚持使用它,也是个好主意。万一有人改变超类中的重写方法名称,子类的方法将不再覆盖它。没有@Override注释,可能不太好找到问题。使用@Override注解,编译器会提示,在子类中的方法没有完全重写超类的方法。
下面我们来看一个例子:

文件:Job.java

package com.yiibai.tutorial.ann.builtin;

public class Job {

    // This is method of Job class.
    public String getName() {
        return null;
    }

}

Java

文件:JavaCoding.java

ckage com.yiibai.tutorial.ann.builtin;

public class JavaCoding extends Job {
    // @Override not required to write on this method.
    @Override
    public String getName() {
        return "Java Coding";
    }
}

Java

这里是Java编译器警告:

2.3. @SuppressWarnings注解

@SuppressWarnings注解使编译器抑制对某个方法的警告。例如,如果一个方法调用的方法已过时,或使一个不安全的类型转换,编译器可能会产生一个警告。可以通过包含使用@SuppressWarnings注解代码的方法标注抑制这些警告。

下面我们来看看一个例子:

文件:SuppressWarningsDemo.java -

package com.yiibai.tutorial.ann.builtin;

import java.util.Date;

public class SuppressWarningsDemo {

   @SuppressWarnings("deprecation")
   public Date getSomeDate() {

       Date date = new Date(2014, 9, 25);
       return date;
   }

}//

Java

编译器警告如下所示:

文件:SuppressWarningsDemo2.java

package com.yiibai.tutorial.ann.builtin;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class SuppressWarningsDemo2 {

  public List<?> getDatas() {
      List<String> list = new ArrayList<String>();
      list.add("One");
      return list;
  }

  @SuppressWarnings({ "deprecation", "unused", "unchecked" })
  public void processDatas() {  


      // You use deprecated Constructor
      // Variable 'date' was created, but not used      
      Date date = new Date(2014, 9, 25);

      // Cast unsafe.
      // Variable 'datas' is created, but not used in the code.      
      List<String> datas= (List<String>) this.getDatas();        
  }

}原文出自【易百教程】,商业转载请联系作者获得授权,非商业请保留原文链接:https://www.yiibai.com/article/detail/8350

Java

编译器警告如下所示:

编译器警告

3. 编写注解

@interface是声明一个注释的关键字,而这个注解非常相似于接口。注解可有或没有元素。注释元素的特点:

  • 没有函数体;
  • 没有函数参数;
  • 返回的声明必须在一个特定的类型:
    • 基本类型 (boolean, int, float,…)
    • 枚举
    • 注解
    • 类(如:String.class)
  • 元素可以有默认值;

3.1. 第一个注解

文件:MyFirstAnnotation.java -

package com.yiibai.tutorial.ann1;

public @interface MyFirstAnnotation {

    // element name.
    public String name();

    // Element description, default value "".
    public String description() default "";  
}

Java

注释可以用在:

  • TYPE - 类,接口(包括注释类型)或枚举声明
  • FIELD - 字段声明(包括枚举常量)
  • METHOD - 方法声明
  • PARAMETER - 参数声明
  • CONSTRUCTOR - 构造函数声明
  • LOCAL_VARIABLE - 局部变量声明
  • ANNOTATION_TYPE - 注解类型声明
  • PACKAGE - 包声明

文件:UsingMyFirstAnnotation.java -

package com.yiibai.tutorial.ann1;

@MyFirstAnnotation(name = "Some name", description = "Some description")
public class UsingMyFirstAnnotation {

    // Annotation on Constructor.
    @MyFirstAnnotation(name = "John", description = "Write by yiibai.com")
    public UsingMyFirstAnnotation() {

    }

    @MyFirstAnnotation(name = "Tom")
    public void someMethod() {

    }

    // An Annotation on parameter of method.
    public void todo(@MyFirstAnnotation(name = "none") String job) {

        // An annotation on local variable.
        @MyFirstAnnotation(name = "Some name")
        int localVariable = 0;

    }

}

Java

3.2. 注解与元素值

注解有一个元素命名值,它有一些特点,参考以下示例代码 -

文件:AnnWithValue.java

package com.yiibai.tutorial.ann2;

public @interface AnnWithValue {

    public int value();

    // Element 'name'.    
    public String name() default "";
}

Java

文件:UsingAnnWithValue.java

package com.yiibai.tutorial.ann2;

public class UsingAnnWithValue {

    @AnnWithValue(name = "Name1", value = 100)
    public void someMethod1() {

    }

    @AnnWithValue(value = 100)
    public void someMethod2() {

    }

    @AnnWithValue(100)
    public void someMethod3() {

    }
}

Java

3.3. @Retention & @Target

@Retention & @Target 是Java 的两个可用的注解。@Retention: 使用时要注意一些注解的存在层次。特别是,有3个级别的所提到东西存在要注意:

  • RetentionPolicy.SOURCE: 存在于源代码,并编译器自由识别。
  • RetentionPolicy.CLASS: 它的存在是由编译器识别,但不是由虚拟机在运行时。
  • RetentionPolicyRUNTIME: 达到存在的最高级别,由编译器和由虚拟机在运行时确定的。

@Target: 在使用时要注意另一个注解及其使用范围。

  • ElementType.TYPE - 附在类,接口,枚举,注解的声明。
  • ElementType.FIELD - 附在字段的声明和枚举常量。
  • ElementType.METHOD - 附在方法的声明。
  • ElementType.PARAMETER - 附在参数的声明
  • ElementType.CONSTRUCTOR - 附在构造函数的声明
  • ElementType.LOCAL_VARIABLE - 附在局部变量
  • ElementType.ANNOTATION_TYPE - 附在注释的声明
  • ElementType.PACKAGE - 附在包的声明;

文件:AnnFM.java -

package com.yiibai.tutorial.ann3;

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

// Annotation are to be discarded by the compiler.
@Retention(value = RetentionPolicy.SOURCE)

// AnnFM will only be used on FIELD or  METHOD.
@Target(value = { ElementType.FIELD, ElementType.METHOD })
public @interface AnnFM {

}

Java

文件:UsingAnnFM.java -

package com.yiibai.tutorial.ann3;

public class UsingAnnFM {

    // AnnFM will only be used on FIELD or  METHOD.
    @AnnFM
    protected int someField = 100;

    // AnnFM will only be used on FIELD or  METHOD.
    @AnnFM
    public void someMethod() {

    }
}

Java

3.4. 注解与反射

Java反射通过一些注解的东西可以识别像类,字段,方法。当然它只能使用@Retention(RetentionPolicy.RUNTIME)识别注解
下面的例子说明一个程序读取原始的Java文件,并创建HTML文件的注释。每个类相当于一个HTML文件。

注解与反射

文件:AnnHtmlUL.java

package com.yiibai.tutorial.ann4;

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

@Retention(RetentionPolicy.RUNTIME)

// Using for Class, interface, annotation, enum.
@Target(value = { ElementType.TYPE })


// Simulating the <UL> in HTML.
public @interface AnnHtmlUL {

    public String border() default "border:1px solid blue;";
}

Java

文件:AnnHtmlLI.java

package com.yiibai.tutorial.ann4;

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


@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD,ElementType.METHOD })


// Simulating the <LI> in HTML.
public @interface AnnHtmlLI {

    public String background();

    public String color() default "red";
}

Java

文件:DocumentClass.java

package com.yiibai.tutorial.ann4;

@AnnHtmlUL(border = "1px solid red")
public class DocumentClass {

    private String author;

    @AnnHtmlLI(background = "blue", color = "black")
    public String getDocumentName() {
        return "Java Core";
    }

    @AnnHtmlLI(background = "yellow")
    public String getDocumentVersion() {
        return "1.0";
    }

    @AnnHtmlLI(background = "green")
    public void setAuthor(String author) {
        this.author = author;
    }

    @AnnHtmlLI(background = "red", color = "black")
    public String getAuthor() {
        return author;
    }

    // This method is not annotated
    public float getPrice()  {
        return 100;
    }

}

Java

文件:HtmlGenerator.java

package com.yiibai.tutorial.ann4;

import java.lang.reflect.Method;

public class HtmlGenerator {

    public static void main(String[] args) {

        Class<?> clazz = DocumentClass.class;

         // Check if this class is annotated by Annotation AnnHtmlUL or not.
        boolean isHtmlUL = clazz.isAnnotationPresent(AnnHtmlUL.class);

        StringBuilder sb = new StringBuilder();
        if (isHtmlUL) {
            // Get the AnnHtmlUL annotation on this class.
            AnnHtmlUL annUL = clazz.getAnnotation(AnnHtmlUL.class);

            sb.append("<H3>" + clazz.getName() + "</H3>");
            sb.append("\n");


            // Get the value of the element 'border'.
            String border = annUL.border();

            sb.append("<UL  + border + "'>");

            // Add new line
            sb.append("\n");

            Method[] methods = clazz.getMethods();

            for (Method method : methods) {
                // Check if this method is annotated by Annotation AnnHtmlLI or not.
                if (method.isAnnotationPresent(AnnHtmlLI.class)) {

                    // Get the annotation
                    AnnHtmlLI annLI = method.getAnnotation(AnnHtmlLI.class);

                    // Get the values of elements.
                    String background = annLI.background();
                    String color = annLI.color();

                    sb.append("<LI 
                            + background + ";color:" + color + "'>");
                    sb.append("\n");
                    sb.append(method.getName());
                    sb.append("\n");
                    sb.append("</LI>");
                    sb.append("\n");
                }
            }
            sb.append("</UL>");
        }
        writeToFile(clazz.getSimpleName() + ".html", sb);
    }

    // Write to Console (Or file)
    private static void writeToFile(String fileName, StringBuilder sb) {
        System.out.println(sb);
    }

}

Java

运行示例得到以下结果:

结果

生成的HTML文件:

生成的HTML文件

原文出自【易百教程】,商业转载请联系作者获得授权,非商业转载请保留原文链接:https://www.yiibai.com/java/java-annotation-tutorial.html
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值