注解(注释类型)
注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件
自定义注解
[修饰符列表] @interface 注解类型名{
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
@MyAnnotation public class AnnotationTest01 {
@MyAnnotation private int no;
@MyAnnotation public AnnotationTest01(){}
@MyAnnotation public static void m1(){ @MyAnnotation int i = 100; }
@MyAnnotation public void m2(@MyAnnotation String name, @MyAnnotation int k){
} }
@MyAnnotation interface MyInterface {
}
@MyAnnotation enum Season { SPRING,SUMMER,AUTUMN,WINTER }
|
JDK内置的注解
java.lang包下的注释类型:
掌握:
Deprecated 用 @Deprecated 注释的程序元素,
不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
掌握:
Override 表示一个方法声明打算重写超类中的另一个方法声明。
不用掌握:
SuppressWarnings 指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。
@Override
源代码:
public @interface Override {
}
标识性注解,给编译器做参考的。
编译器看到方法上有这个注解的时候,编译器会自动检查该方法是否重写了父类的方法。
如果没有重写,报错。
这个注解只是在编译阶段起作用,和运行期无关!
@Override这个注解只能注解方法。
@Override这个注解是给编译器参考的,和运行阶段没有关系。
凡是java中的方法带有这个注解的,编译器都会进行编译检查,如果这个方法不是重写父类的方法,编译器报错。
1 2 3 4 5 6 7 8 9 10 11
| public class AnnotationTest02 {
private int no;
@Override public String toString() { return "toString"; }
}
|
@Deprecated
Deprecated 用 @Deprecated 注释的程序元素,
不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.bjpowernode.java.annotation;
@Deprecated public class AnnotationTest03 {
@Deprecated private String s;
public static void main(String[] args) { AnnotationTest03 at = new AnnotationTest03(); at.doSome(); }
@Deprecated public void doSome(){ System.out.println("do something!"); }
@Deprecated public static void doOther(){ System.out.println("do other..."); } }
class T { public static void main(String[] args) { AnnotationTest03 at = new AnnotationTest03(); at.doSome();
AnnotationTest03.doOther();
try { Class c = Class.forName("java.util.Date"); Object obj = c.newInstance(); } catch (Exception e) { e.printStackTrace(); } } }
|
注解中定义属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class MyAnnotationTest {
@MyAnnotation(name = "zhangsan", color = "红色") public void doSome(){
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public @interface MyAnnotation {
String name();
String color();
int age() default 25;
}
|
如果一个注解的属性的名字是value,并且只有一个属性的话,在使用的时候,该属性名可以省略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class MyAnnotationTest {
@MyAnnotation(value = "hehe") public void doSome(){
}
@MyAnnotation("haha") public void doOther(){
} }
|
1 2 3 4 5 6 7 8 9
| public @interface MyAnnotation {
String value();
}
|
注解当中的属性可以是哪一种类型?
属性的类型可以是:
byte short int long float double boolean char String Class 枚举类型
以及以上每一种的数组形式。
元注解
用来标注“注解类型”的“注解”,称为元注解。
常见的元注解 Target
Retention
关于Target注解:
这是一个元注解,用来标注“注解类型”的“注解”
这个Target注解用来标注“被标注的注解”可以出现在哪些位置上。
@Target(ElementType.METHOD):表示“被标注的注解”只能出现在方法上。
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
表示该注解可以出现在:
构造方法上
字段上
局部变量上
方法上
….
类上…
关于Retention注解:
这是一个元注解,用来标注“注解类型”的“注解”
这个Retention注解用来标注“被标注的注解”最终保存在哪里。
@Retention(RetentionPolicy.SOURCE):表示该注解只被保留在java源文件中。
@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中。
@Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制所读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.bjpowernode.java.annotation5;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation {
String value() default "北京大兴区"; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ReflectAnnotationTest { public static void main(String[] args) throws Exception{ Class c = Class.forName("com.bjpowernode.java.annotation5.MyAnnotationTest"); if(c.isAnnotationPresent(MyAnnotation.class)){ MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class); String value = myAnnotation.value(); System.out.println(value); }
Class stringClass = Class.forName("java.lang.String"); System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class)); } }
|
通过反射机制获取注解对象属性的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation {
String username();
String password(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.lang.reflect.Method;
public class MyAnnotationTest {
@MyAnnotation(username = "admin", password = "456456") public void doSome(){
}
public static void main(String[] args) throws Exception{ Class c = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest"); Method doSomeMethod = c.getDeclaredMethod("doSome"); if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class); System.out.println(myAnnotation.username()); System.out.println(myAnnotation.password()); } }
}
|
注解在开发中的作用
需求:
假设有这样一个注解,叫做:@Id
这个注解只能出现在类上面,当这个类上有这个注解的时候,
要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常。如果有这个属性则正常执行!
1 2 3 4 5 6 7 8
| public class HasNotIdPropertyException extends RuntimeException { public HasNotIdPropertyException(){
} public HasNotIdPropertyException(String s){ super(s); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) public @interface MustHasIdPropertyAnnotation {
}
|
1 2 3 4 5 6
| @MustHasIdPropertyAnnotation public class User { int id; String name; String password; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.lang.reflect.Field;
public class Test { public static void main(String[] args) throws Exception{ Class userClass = Class.forName("com.bjpowernode.java.annotation7.User"); if(userClass.isAnnotationPresent(MustHasIdPropertyAnnotation.class)){ Field[] fields = userClass.getDeclaredFields(); boolean isOk = false; for(Field field : fields){ if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){ isOk = true; break; } }
if(!isOk){ throw new HasNotIdPropertyException("被@MustHasIdPropertyAnnotation注解标注的类中必须要有一个int类型的id属性!"); }
} } }
|