java注解
分类:
源码注解:只在编译器存在 变成 class 文件时不存在
编译时注解:注解再源码和。class 文件中都存在 Override
运行时注解:运行阶段还起作用,甚至会影响运行逻辑 AutoWired
自定义注解:
Inherited 父类有这个注解 子类默认就有
自定义 java 注解 TestAnnotation:并且为两个属性设置默认值
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public int id() default -1;
public String msg() default "hello";
}
Check 注解 自定义 当注解只有一个属性的时候默认属性名为 value
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
String value();
}
没有任何属性的注解 Perform
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Perform {
}
Java 内置的注解:
@Deprecated:表示一个元素已经过时 例如过时的方法、类、成员变量。
public class Hero {
@Deprecated
public void say(){
System.out.println("hero say method");}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak(){
System.out.println(</span>"hero speak method"<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero();
hero.speak();
hero.say();;
}
</span></span></pre>
@Override:表示对父类中方法的重写
public class Child extends Father{
@Override
public void method() {
System.out.println("child method");}
}
class Father{
public void method(){
System.out.println("fathre method");}
}
@SuppressWarnings: 阻止警告 被 Deprecated 注解的方法,编译器会警告提示,使用这个注解可以屏蔽掉警告
@SuppressWarnings("deprecation")
public class Hero {
@Deprecated
public void say(){
System.out.println("hero say method");}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> speak(){
System.out.println(</span>"hero speak method"<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero();
hero.speak();
hero.say();
}
}
@SafeVarargs: 参数安全类型注解。提醒开发者不要用啊参数做一些不安全的操作,使用该注解会阻止编译器产生 Unchecked 这样的警告
@SafeVarargs // Not actually safe!
static void m(List<String>... stringLists) {Object[] array = stringLists;
List<Integer> tmpList = Arrays.asList(42);
array[0] = tmpList; // Semantically invalid, but compiles without warnings
String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}
@FunctionalInterface:java1.8 的新特性 函数式接口 lambda 表达式 例如 Runnable 接口 是一个函数式接口 很容易转换为 lambda
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();}
注解的提取:
注解和反射:
注解通过反射获取。使用 isAnnotationPresent 方法判断它是否应用了某个注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass){}
通过 getAnnotation 方法获取 Annotation 对象 返回制定类型的注解
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
或者是 getAnnotations() 方法 返回注解到这个元素上的所有注解
public Annotation[] getAnnotations() {}
代码示例:
@TestAnnotation
public class Test {
public static void main(String[] args) {
boolean hasAnn = Test.class.isAnnotationPresent(TestAnnotation.class);
if (hasAnn) {
TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
System.out.println("id:" + testAnnotation.id());
System.out.println("msg:" + testAnnotation.msg());}
}
}
属性和方法上的注解同样可以获取到:通过 java 反射
@TestAnnotation(msg = "qwert") public class Test {@Check(</span>"hi"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> a; @Perform </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test(){} @SuppressWarnings(</span>"deprecation"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> test1(){ Hero hero </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hero(); hero.speak(); hero.say(); } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) { </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAnn = Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.isAnnotationPresent(TestAnnotation.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAnn) { TestAnnotation testAnnotation </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getAnnotation(TestAnnotation.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"id:" +<span style="color: rgba(0, 0, 0, 1)"> testAnnotation.id()); System.out.println(</span>"msg:" +<span style="color: rgba(0, 0, 0, 1)"> testAnnotation.msg()); } </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{ Field a </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredField("a"<span style="color: rgba(0, 0, 0, 1)">); a.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取一个成员变量上注解</span> Check check = a.getAnnotation(Check.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span>(check!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){ System.out.println(</span>"check value :"+<span style="color: rgba(0, 0, 0, 1)">check.value()); } Method testMethod </span>= Test.<span style="color: rgba(0, 0, 255, 1)">class</span>.getDeclaredMethod("test"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">if</span>(testMethod!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){ Annotation[] anns</span>=<span style="color: rgba(0, 0, 0, 1)"> testMethod.getAnnotations(); </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(Annotation ann : anns){ System.out.println(ann.annotationType().getSimpleName()); } } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchFieldException e) { e.printStackTrace(); } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchMethodException e) { e.printStackTrace(); } }
}
java 官方文档对注解的解释:
注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。 注解有许多用处,主要如下: - 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息 - 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html 文档或者做其它相应处理。 - 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取
注解不是代码本身的一部分
当开发者使用了 Annotation 修饰了类、方法、Field 等成员之后,这些 Annotation 不会自己生效,必须有开发者提供相应的代码来提取并处理 Annotation 信息。这些提取和处理 Annotation 的代码统称为 APT(Annotation Processing Tool)。
示例:
定义注解 Jiecha
@Retention(RetentionPolicy.RUNTIME) public @interface Jiecha { }
NoBug.java
public class NoBug {@Jiecha </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> suanshu(){ System.out.println(</span>"123456"<span style="color: rgba(0, 0, 0, 1)">); } @Jiecha </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> jiafa(){ System.out.println(</span>"1+1="+1+1<span style="color: rgba(0, 0, 0, 1)">); } @Jiecha </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> jianfa(){ System.out.println(</span>"1-1="+(1-1<span style="color: rgba(0, 0, 0, 1)">)); } @Jiecha </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> chengfa(){ System.out.println(</span>"3*5="+(3*5<span style="color: rgba(0, 0, 0, 1)">)); } @Jiecha </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> chufa(){ System.out.println(</span>"6/0="+6/0<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> desc(){ System.out.println(</span>"this is a noBug class desc"<span style="color: rgba(0, 0, 0, 1)">); }
}
TestTool.java 测试 NoBug 的方法
public class TestTool { public static void main(String[] args) { NoBug noBug = new NoBug(); Class clazz = noBug.getClass(); //反射获取方法 Method[] methods=clazz.getDeclaredMethods(); //用来记录测试产生的 log 信息 StringBuilder log = new StringBuilder(); //记录异常的次数 int errorNum =0;</span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(Method method : methods){ </span><span style="color: rgba(0, 0, 255, 1)">if</span>(method.isAnnotationPresent(Jiecha.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)){ </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { method.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">); method.invoke(noBug,</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">catch</span> (IllegalAccessException |<span style="color: rgba(0, 0, 0, 1)"> InvocationTargetException e) { errorNum</span>++<span style="color: rgba(0, 0, 0, 1)">; log.append(method.getName()); log.append(</span>" "<span style="color: rgba(0, 0, 0, 1)">); log.append(</span>"has error:"<span style="color: rgba(0, 0, 0, 1)">); log.append(e.getCause().getClass().getSimpleName()); log.append(</span>"\n\r"<span style="color: rgba(0, 0, 0, 1)">); log.append(e.getCause().getMessage()); log.append(</span>"\n\r"<span style="color: rgba(0, 0, 0, 1)">); } } } log.append(clazz.getSimpleName()); log.append(</span>" has "<span style="color: rgba(0, 0, 0, 1)">); log.append(errorNum); log.append(</span>" error."<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成测试报告</span>
System.out.println(log.toString());
}
}
结果:
3*5=15 1+1=11 123456 1-1=0 chufa has error:ArithmeticException / by zero NoBug has 1 error.