Java注解
1- 什么是注解?
1.1- 编译指令
1.2- 编译时指令
1.3- 运行时指令
2- 内置注解
2.1- @Deprecated
2.2- @Override
2.3- @SuppressWarnings
3- 编写注解
3.1- 你的第一个注解
3.2- 注解与元素值
3.3- @Retention & @Target
3.4- Annotation & Reflection
4- 注解处理工具 (高级知识)
1- 什么是注解
Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。
-
编译器指令
</li>
-
编译时指令
</li>
-
运行时指令
</li>
1.1- 编译指令
- @Deprecated
- @Override
- @SuppressWarnings
1.2- 编译时指令
当你创建建软件项目时,Java 注释可以在编译时使用。构建过程包括生成的源代码,编译源文件,生成 XML 文件 (例如部署描述符),包装编译代码和文件到一个 JAR 文件等。构建软件通常是通过像 Apache Ant 组织的 Apache Maven 的自动构建工具完成。 构建工具可以扫描你的 Java 代码指定的注解并生成源代码或基于这些注解其他文件。
1.3- 运行时指令
通常情况下,Java 注解中不存在于编译后的 Java 代码。这是可能的,但是,定义自己的注解是在运行时可用。这些注解然后可以通过 Java 反射访问,并用于发出指令到您的程序,或者一些第三方 API。
2- 内置注解
- @Deprecated
- @Override
- @SuppressWarnings
</div>
2.1- @Deprecated
这是用来注解过时的东西,如类或方法的注解; 最好我们不应该再使用它。
如果你使用的东西过时,编译器会通知您应该使用的另一种方式。
- DeprecatedMethodDemo.java
</div>
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();
}
}
2.2- @Override
@Override 注解来覆盖超类方法在方法使用。如果这个方法不超匹配的方法,编译器就会给你一个错误。
要覆盖超类的方法而使用 @Override
注解是没有必要的。如仍然使用它,也是个好主意。万一有人改变超类中的重写方法名称,子类的方法将不再覆盖它。 没有 @Override 注释,你不好找到问题答案。有了 @Override 注解,编译器会告诉你,在子类中的方法不重写超类的任何方法。
- Job.java
</div>
package com.yiibai.tutorial.ann.builtin;public class Job {
// This is method of Job class. public String getName() { return null; }
}
- JavaCoding.java
ckage com.yiibai.tutorial.ann.builtin;public class JavaCoding extends Job {
// This method is overridden method getName() of the superclass. // @Override not required to write on this method. // But it is necessary if someone changed the name of the method getName() // in parent class, an error message will tell you. @Override public String getName() { return "Java Coding"; }
}
2.3- @SuppressWarnings
@SuppressWarnings 注解使编译器抑制对某个方法的警告。例如,如果一个方法调用的方法已过时,或使一个不安全的类型转换,编译器可能会产生一个警告。您可以通过包含使用 @SuppressWarnings 注解代码的方法标注抑制这些警告。
- SuppressWarningsDemo.java
</div>
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;
}
}
- SuppressWarningsDemo2.java
</div>
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();
}
}
3- 编写你自己的注解
@interface 是声明一个注释的关键字,而这个注解非常相似于接口。注解可有或没有元素。注释元素的特点:
-
没有函数体
</li>
-
没有函数参数
</li>
-
返回的声明必须在一个特定的类型:
- 基本类型 (boolean, int, float,...)
-
枚举
</li>
-
注解
</li>
-
类 (如:String.class)
</li>
</li>
-
元素可以有默认值
</li>
3.1- 你的第一个注解
- MyFirstAnnotation.java
</div>
package com.yiibai.tutorial.ann1;public @interface MyFirstAnnotation {
// element name. public String name(); // Element description, default value "". public String description() default "";
}
- 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. // The value of the element name is "John" // Value element description is "Write by John". @MyFirstAnnotation(name = "John", description = "Write by John") public UsingMyFirstAnnotation() { } // Annotation tied up method. // The value of the element name is "Tom" // Description element is not declared, it will be assigned a default value @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; }
}
3.2- 注释与元素值
- AnnWithValue.java
package com.yiibai.tutorial.ann2;public @interface AnnWithValue {
// Element named 'value' // There is a bit special when using this element. public int value(); // Element 'name'. public String name() default "";
}
- UsingAnnWithValue.java
package com.yiibai.tutorial.ann2;public class UsingAnnWithValue {
@AnnWithValue(name = "Name1", value = 100) public void someMethod1() { } // Initialize the elements of Annotation in the usual way. // Element 'name' using default. @AnnWithValue(value = 100) public void someMethod2() { } // With element 'value', you can just write out the value of it. @AnnWithValue(100) public void someMethod3() { }
}
3.3- @Retention & @Target
@Retention & @Target 是 Java 的两个可用的注解。@Retention: 使用时要注意一些注解的存在层次。
- RetentionPolicy.SOURCE: 存在于源代码,并编译器自由识别。
- RetentionPolicy.CLASS: 它的存在是由编译器识别,但不是由虚拟机在运行时。
- RetentionPolicyRUNTIME: 达到存在的最高级别,由编译器和由虚拟机在运行时确定的。
- ElementType.TYPE - 附在类,接口,枚举,注解的声明。
- ElementType.FIELD - 附在字段的声明和枚举常量。
- ElementType.METHOD - 附在方法的声明。
- ElementType.PARAMETER - 附在参数的声明
- ElementType.CONSTRUCTOR - 附在构造函数的声明
- ElementType.LOCAL_VARIABLE - 附在局部变量
- ElementType.ANNOTATION_TYPE - 附在注释的声明
- ElementType.PACKAGE - 附在包的声明
- AnnFM.java
</div>
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 {}
- 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() { }
}
3.4- 注解与反射
Java 反射通过一些注解的东西可以识别像类,字段,方法。当然它只能使用 @Retention(RetentionPolicy.RUNTIME) 识别注解- AnnHtmlUL.java
</div>
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;";
}
- 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";
}
- 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; }
}
- 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 style='border:" + 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 style='margin:5px;padding:5px;background:" + 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); }
}
4- 注解处理工具 (高级知识)
您可以创建自己的注解,并在 Java 应用程序中使用它们。您将使用这些注解规则。要 Java 编译器来通知应用错误的规则,在编译时的错误。
</div>