typora-root-url: images
一、注解
1.1、概述
- 从JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)
- Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
- Annotation 可以像修饰符一样被使用, 可用于修饰包,类, 构造器, 方法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在Annotation 的“name=value” 对中。
- 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置等。
- 未来的开发模式都是基于注解的。
1.2、Java中的常见注解
1.2.1、图示
@Override:一般在实现了接口的方法上标识,作用是告诉编译器该方法是接口的方法,表示重写。
@Deprecated:一般在接口中的方法上进行标识,作用是该方法过时了。
@Suppvisewarnings:忽视警告,@SuppressWarnings("deprecation")
1.2.2、代码示例
-
创建Person类
public interface Person { public String name(); public int age(); @Deprecated public void sing(); }
-
创建Child.java类,并实现Person.java类
public class Child implements Person { @Override public String name() { return null; } @Override public int age() { return 0; } @Override public void sing() { } }
-
创建测试类Test.java
public class Test { public void sing(){ Person p = new Child(); p.sing(); } }
-
此时调用的sing()会有一条横切线标识,标识当前方法即将过期或失效。
1.2.3、问题解决
此时为了解决这个问题,可以在方法明上添加一个@SuppressWarnings('deprecation')注解,用于标识忽略这个警告。
注意:sing()是过期的方法,一般都是旧版本jdk中使用的,在新的jdk版本中虽然还能用,但是,类似这样的方法大部分存在是为了保证其它旧的项目能够正常运行,而新开发的项目已经不再使用或使用可替代的方法。
1.3、Java第三方注解
1.3.1、图示
1.3.2、说明
第三方的注解(Spring、Mybatis框架中的注解),这些也是比较常见的,功能相对也比较简单,但是对于编程而言,大大的减少代码量,简化了,程序在形式上的编写。
Spring:@Autowired @Service @Repository
@Autowired:可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。通过 @Autowired的使用来消除 set ,get方法。
public class UserManagerImpl implements UserManager {
@Autowired
private UserDao userDao;
}
@Service:用于标注业务层组件。定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX。而无需去xml文件内去配置。
@Repository:用于标注数据访问组件,即DAO组件。
二、注解分类
2.1、说明
1、按照运行机制分为
源码注解:注解只在源码中存在,编译成.class文件就不存在了
编译时注解:注解在源码和.class文件中都存在(如:JDK内置系统注解:@Override、@Deprecated、@Suppvisewarnings)
运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解(如:Spring中@Autowried,程序运行时,把成员变量自动注入)
2、按照来源分为:
JDK内置系统注解、自定义注解、第三方注解
3.元注解:
给注解进行注解,注解的注解
三、自定义注解
3.1、Java自定义注解
3.1.1、说明要求
- 使用@interface关键字定义注解
- 成员以无参无异常方式声明
- 可以用default为成员指定一个默认值
- 如果注解只有一个成员,则成员名必须取名value(),在使用时可以忽略成员名和赋值号(=);
- 成员类型是受限的,合法的类型包括原始类型String,Class,Annotation,Enumeration
- 注解类可以没有成员,没有成员的注解称为标识注解
3.1.2、图示
3.1.3、元注解
- @Documented 生成javadoc时包含注解
- @Inherited 允许子类继承
- @Retention(RetentionPolicy.RUNTIME):声明周期
- SOURCE只在源码显示,编译时会丢弃;
- CLASS编译时会记录到class中,运行时忽略;
- RUNTIME运行时存在,可以通过反射读取]
- @Target({ElementType.METHOD})
- CONSTRUCTOR构造方法声明;
- FIELD字段声明;
- LOCAL_VARIABLE局部变量声明;
- METHOD方法声明;
- PACKAGE包声明;
- PARAMETER参数声明;
- TYPE类接口
3.1.4、图示
3.2、使用自定义注解
3.2.1、格式
自定义注解的使用
@<注解名>(<成员名1>=<成员值1>,<成员名1>=<成员值1>,...)
3.2.2、示例
@Description(desc="I am HelloWorld",author="guoguo")
public String HelloWorld(){
return "今天天气很晴朗";
}
3.3、关于自定义注解的代码演示说明
3.3.1、说明
自定义注解时,如果注解只有一个成员,则成员名必须为value(),在使用是可以忽略成员名称赋值号(=)。
3.3.2、详解
-
说明1
@Description(desc="the name method")。不会报错。但不符合规范,既然只有一个成员,就要使用value作为成员名,改成:
public @interface Description{ String value(); }
然后在使用注解的时候,直接赋值,不写成员名和等号:@Description("the name method")
以上方式,约定俗成,比较直观。 -
说明2
没有成员的注解——标志注解(比如常见的@Override),在使用的时候不加括号。
-
说明3
当一个方法被规定为({ElementType.METHOD})就表示只能用于方法的注解,如果用在类上面,就会报错(添加 ElementType.TYPE 则可适用于类)。这里没有包含关系,例如只写ElementType.TYPE 则不能对方法进行注解,只能对类或接口进行注解。
-
说明4
@Documented(属于标识注解,生成javadoc时会包含注解)
3.4、解析注解
3.4.1、说明
通过反射获取类、方法或成员的运行时注解信息,从而实现动态控制程序运行的逻辑
@Inherited 只能实现类的继承,而接口是无法继承的。即接口的注解无法影响到实现接口的类上面。另外,父类的方法的注解也无法被子类继承。
3.4.2、代码实现
public static void main(String[] args){
//1. 使用类加载器加载类
Class c = Class.forName("anno.test.Child");
//2. 找到类上面的注解,isAnnotationParse()判断类上是否存在Description这样的注解
boolean isExist=c.isAnnotationPresent(Description.class);//
if(isExist){
//3.获得注解实例
Description d = (Description)c.getAnnotation(Description.class);
System.out.println(d.value());
}
//4.找到方法上的注解
// 获取方法上的注解,首先,遍历所有方法,通过方法对象的isAnnotation查看是否有自定义注解
// 如果存在则输出方法的自定义注解的信息。
Method[] mts = c.getMethods();
for (Method mt : mts) {
if(mt.isAnnotationPresent(Description.class)){
Description d2 = (Description)mt.getAnnotation(Description.class);
System.out.println(d2.value());
}
}
}
3.4.3、代码实现2
第二种解析方法:获取这个方法的所有注解,Annotation [] as=m.getAnnotations();然后遍历该注解,如果遍历的注解是Description类型,则把遍历的注解强转为Description类型,并进行输出value()信息。
public static void main(String[] args){
//另外一种获取类上的注解的途径
Annotation[] annos = c.getAnnotations();
for (Annotation anno : annos) {
if(anno instanceof Description){
System.out.println(((Description) anno).value());
}
}
//另一种获取方法上的注解的途径
for (Method mt : mts){
Annotation[] annos2 = mt.getAnnotations();
for (Annotation anno : annos2) {
if(anno instanceof Description){
System.out.println(同上);
}
}
}
}
标签:15,Description,class,public,注解,方法,Annotation
From: https://www.cnblogs.com/rito-blog/p/16929271.html