注解的作用
我们常见的@Override
就是表示重写父类方法的注解,如果重写的方法名出错,编译器就会显示出错误,便于检查。
注解可以理解为一个标志,如果加上注解,就相当于对接下来的代码块做出了一定的规范,别人看到也很方便理解。
常见注解及自定义注解
1、标识性注解
注解 | 作用 |
---|---|
@Override | 只是给给编译器参考,错误以下滑波浪线的形式给出。只可以注解方法,表示该方法是重写的 |
@Deprecated | 运行态的注解,错误出现在编译运行后的控制台。表示注解的部分已经过时,最好不要使用 ,外部调用时往往会有中横线 |
2、元注解
元注解用来注解其它的注解。
注解 | 作用 |
---|---|
@Target(ElementType[] value() | 标识其修饰的注解可以出现的地方,比如类、方法、属性等 |
@Retention( RetentionPolicy value()) | 标识其修饰的注解最终保存的地方,有源文件、class文件、class文件并能被反射机制获取 |
3、自定义注解
形如public @interface NameChecker(注解名称)
,注解有自己的属性,必须在属性名之后加()
,如String name()
。注解一旦有了属性,利用时要给属性赋值,赋值时格式也很固定,如name = "xxx"
。
小技巧
- 如果属性只有一个且属性名为
value
,赋值时就可以省略value,例如@Retention(RetentionPolicy.RUNTIME)
; - 如果有一个属性为数组,但是赋值时数组只有一个元素,可省略
{}
,例如@Target(ElementType.TYPE)
。
实际应用
比如需要Student
类必须要有String name
这一属性,可通过注解与反射的方法实现。
//类所在的包
package From0To100.Reflect.Annotation;
//自定义注解
@Retention(RetentionPolicy.RUNTIME)
public @interface NameChecker {
}
//学生类
@NameChecker
public class Student {
private int age;
private String name;
}
//异常类
public class NameNotFindException extends Exception {
public NameNotFindException() {
}
public NameNotFindException(String message) {
super(message);
}
}
//测试类
public class TestAnnotation {
public static void main(String[] args) throws Exception {
//获取学生的Class
Class studentClass=Class.forName("From0To100.Reflect.Annotation.Student");
if(studentClass.isAnnotationPresent(NameChecker.class)){
//检查所有的属性
Field[] studentFields=studentClass.getDeclaredFields();
boolean flag=false;
for(Field field:studentFields){
if("name".equals(field.getName())&&"String".equals(field.getType().getSimpleName())){
flag=true;
break;
}
}
//不满足条件抛出异常
if(!flag){
throw new NameNotFindException("此类缺少String类型的name域");
}
}
}
}
有问题欢迎交流~