java基础-注解
以下为本人的学习笔记
1.认识Annotation
JDK1.5开始,java增加了对元数据(即类的组成单元数据)的支持,也就是(Annotation)注解,它是代码里做的特殊标记,这些标记可以在编译,类加载,运行时在不改变原有逻辑的情况下,被读取(通过反射来读取),并执行相应 的处理,通过使用Annotation,程序员可以在源文件中嵌入一些补充从信息。代码分析工具,开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。Annotation类似于修饰符一样被使用,可以用于包,类,构造方法,方法,成员变量,局部变量的声明。
元数据可以说是一个属性,解释数据的数据。如一个属性age的值为18,那么这个解释18的字段age就是元数据。
注解也可以说是一个描述信息,把信息再解析。
注解的本质是标记,他所有的功能都依赖于对于这个注解解释性的代码,通常需要结合反射来编写解释下代码。
注意:
Annotation是一个接口
java.lang.Annotation接口
2.系统定义的Annotation
在JDK1.5之后,在系统中提供了三个Annotation,分别是:@Override(译:覆盖)、@Deprecated(译:已弃用)、@SupperssWarings。
@Override
表示验证当前的方法是否覆盖超类中的方法(即重写父类方法)。如果你一不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示
@Deprecated
表示的是一个类或方法已经不再建议继续使用了,标记为已过时
@SupperssWarings
表示关闭不当的编译器警告信息
Annotation | 说明 |
---|---|
@SupperssWarings(“unchecked”) | 未检查的转化,如集合没有指定类型 |
@SupperssWarings(“unused”) | 未使用的变量 |
@SupperssWarings(“resource”) | 有泛型未指定类型 |
@SupperssWarings(“path”) | 在类路径,原文件路径中有不存在的路径 |
@SupperssWarings(“deprecation”) | 使用了某些不赞成使用的类和方法 |
@SupperssWarings(“fallthrough”) | switch语句执行到底没有break关键字 |
@SupperssWarings(“serial”) | 某类实现Serializable但是没有定义serialVersionUID这个需要但是不必须的字段 |
@SupperssWarings(“rawtypes”) | 没有传递带有泛型的参数 |
@SupperssWarings(“all”) | 全部类型的警告(用这一条就够了) |
3.自定义Annotation
注解应用三个步骤:
1)编写注解
2)在类上应用注解
3)对应用了注解的类进行反射操作的类
自定义Annotation的语法如下:
访问控制权限@interface Annotation 名称{}
@interface : 定义一个注解的关键字
例如:
public @interface MyAnnotation{}
//1.自定义注解
//表示该注解的作用范围在运行时存在
@Retention(RetentionPolicy.RUNTIME)
//用于生成文档
@Documented
//用于表示注解的应用范围(类型,方法,属性,构造器,参数,局部变量,包,Annotation)
@Target(ElementType.TYPE)
@Inherited//子类可继承
public @interface MyAnnotation{
//定义变量,注意:变量后要加括号(),且调用此注解时必须设置变量名
public String name();
public int age() default 2;//给变量设置默认值
public String[] like();//定义一个数组,调用此注解时变量名要含大括号{}
public COlor color();//定义一个枚举类型的变量
}
public enum Color{
RED,GREEN,BLUE;
}
//2.使用注解
@MyAnnotation(name="wan",like = {"金鱼","草鱼"},color = Color.RED)
public class Cat{
private String name;
private int age;
public String[] like;
private Color color;
...(构造方法,getter(),setter())
}
public class AnnotationDemo{
/**
反射来处理注解
*/
@Test
public void test2(){
Class<Cat> catClass = Cat.class;
//获取类上应用的指定注解
MyAnnotation annotation = CatClass.getAnnotation(MyAnnotation.class);
//获取注解上变量值
String name = annotation.name();
int age = annotation.age();
Color color = annotation.color();
String[] like = annotation.like();
try{
//通过反射实例化对象,调用对象的方法存储注解上的值
Cat cat =catClass.newInstance();
cat.setName(name);
cat.setAge(age);
cat.setLike(like);
cat.setColor(color);
System.out.println(cat);
}catch(InstantiationException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}
}
}
4.Retention和RetentionPolicy
Annotation要想决定其作用的范围,通过@Retention(译:保持)指定,而Retention指定的范围由RetentionPolicy(policy,译:方针,政策,原则)决定,RetentionPolicy指定了三种范围:
范围 | 说明 |
---|---|
public static final RetentionPolicy SOURCE | 在java源程序中存在(提供给编译器使用) |
public static final RetentionPolicy CLASS | 在java生成的class存在 |
public static final RetentionPolicy RUNTIEM | 在java运行的时候存在(我们通常使用这个范围) |
示例:
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
public String name();
}
5.反射与Annotation
一个Annotation真正起作用,必须结合反射机制,在反射中提供了以下的操作方法:
java.lang.reflect.AccessibleObject(供虚拟机使用)
Method | 说明 |
---|---|
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) (present,译:目前,出现) | 判断是否是指定的Annotation |
public Annotation[] getAnnotations() | 得到全部的Annotation |
public Annotation getAnnotation(Annotation.class) | 获取指定的Annotation |
注解在目前而言最主流的应用就是代替配置文件,例如Spring、SpringBoot等,注解具有开发效率高,成本低的特点,缺点是耦合性高,不利于维护
6.@Documented注解
此注解表示的是文档化,可以在生成doc文档的时候添加注解,即生成文档时,注释一起生成
7.@Target注解
@Target注解(用来注释注解)表示的是一个Annotation的使用范围,例如:之前定义的MyAnnotation可以在任意的位置上使用(没有写这个注解,就所有地方可以使用)
范围 | 说明 |
---|---|
public static final ElementType TYPE | 只能在类或接口或枚举上使用 |
public static final ElementType FIELD | 在成员变量中使用 |
public static final ElementType METHOD | 在方法中使用 |
public static final ElementType PARAMETER | 在参数上使用 |
public static final ElementType CONSTRUCTOR | 在构造中使用 |
public static final ElementType LOCAL_VARIABLE | 局部变量上使用 |
public static final ElementType ANNOTATION_TYPE | 只能在Annotation中使用 |
public static final ElementType PACKAGE | 只能在包中使用 |
8.@Inherited注解
@Inherited表示一个Annotation是否允许被其子类继承下来(使用时表示允许)
9.面试题:
1、什么是注解?以及它的作用?
从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)。
Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。
Annotation 可以像修饰符一样被使用, 可用于修饰包, 类, 构造器, 方法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在Annotation 的 “name=value” 对中。
2、JAVASE常用的注解?
@Override: 限定重写父类方法, 该注解只能用于方法;在编译期检测是否是重写的方法;
@Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择;
@SuppressWarnings: 抑制编译器警告;
3、怎么自定义注解?
1)、定义新的 Annotation 类型使用 @interface 关键字,自定义注解自动继承了java.lang.annotation.Annotation接口。
2)、Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能是八种基本数据类型、String类型、Class类型、enum类型、Annotation类型、以及所有类型的数组。
3)、我们自定义的注解,如果有成员变量,那么在使用的时候必须赋值;如果自定义的注解的成员变量,赋予了默认值,那么我们使用的时候可以赋值,也可以不赋值; 我们需要default来给注解的成员变量赋值
4)、如果只有一个参数成员,建议使用参数名为value;
5)、没有成员定义的 Annotation 称为标记; 包含成员变量的 Annotation 称为元数据 Annotation; 我们都可以称之为注解;
4、什么元注解,元注解有哪些,作用是什么?
JDK 的元 Annotation 用于修饰其他 Annotation 定义;
@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个RetentionPolicy 类型的成员变量, 使用@Rentention 时必须为该 value 成员变量指定值: RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释;
RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行 Java 程序时, JVM 不会保留注解。 这是默认值;
RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行 Java 程序时, JVM 会保留注释。程序可以通过反射获取该注释。
@Target: 用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。
@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。
@Inherited: 被它修饰的 Annotation 将具有继承性。
■免责申明
⒈ 本站是纯粹个人学习网站,与朋友交流共赏,不存在任何商业目的。
⒉ 本站利用了部分网络资源,版权归原作者及网站所有,如果您对本站所载文章及作品版权的归属存有异议,请立即通知我们,我们将在第一时间予以删除,同时向你表示歉意!