注解(Annotation)
基本注解
@SuppressWarnings
参数:
1, deprecation:使用了过时的类或方法时的警告
2, unchecked:执行了未检查的转换时的警告
3, fallthrough:当switch程序块直接通往下一个情况而没有break时的警告
4, path:在类路径,源文件路径等中有不存在的路径时的警告
5, serial:当在可序列化的类上缺少serialVersionUID时的警告
6, finally:任何finally语句不能正常完成时的警告
7, all:关于以上所有情况的警告
@Override
作用:保证编译时,Override函数声明的正确性
@Deprecated
作用:对不应该使用的方法添加注释(还不如javadoc中的Deprecated ,因为不支持参数)
元注解
@Retention
定义在一个注解类的前面,用来说明注解的生命周期。
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
RetentionPolicy.SOURCE
@Target
它是被定义在一个注解类的前面,用来说明该注解可以被声明在哪些元素前
ElementType.PACKAGE
ElementType.CONSTRUCTOR
ElementType.TYPE
ElementType.METHOD
ElementType.FIELD
ElementType.PARAMETER
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE
@Documented
用于描述其它类型的annotation应该被作为被标注的程序成员的公共API
因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员
Eg:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
public String name() default "fieldName";
public String setFuncName() default "setField";
public String getFuncName() default "getField";
public boolean defaultDBValue() default false;
}
@Inherited
作用:允许子类继承父类的注释。
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的.
如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类.
注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继 承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现, 或者到达类继承结构的顶层。
Eg:
@Inherited
public @interface Greeting {
public enum FontColor{ BULE,RED,GREEN};
String name();
FontColor fontColor() default FontColor.GREEN;
}
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口.
由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置 参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default 来声明参数的默认值。
注解的生命周期:
使用@Retention
@Retention(RetionPolicy.SOURCE)
注解保留在源文件中,当编译成class文件时,注解不将源文件中的注解编译到class文件中。
@Retention(RetionPolicy.CLASS)
注解只保留在CLASS文件中,当加载class到内存时,虚拟机会将注解去掉,从何在程序中部能访问。
@Retention(RetionPolicy.RUNTIME)
说明注解在程序运行期间都会保留到内存中。我们可以通过反射来获取定义在某个类上的所有注解。
注解的定义
public @interface MyAnnotation{
//定义公共的final 静态属性
//定义公共的抽象方法
}
注解可以定义哪些成员
同接口定义相似,可以是final静态属性,和abstract抽象方法
注解的方法:
1默认在方法前面加上 public abstract
2,在定义方法时候,可以定义方法的默认返回值
Eg,String color() default “blue”;
String[] color() default {“blue”,”red”};
注解的返回类型 :
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组注解的使用:
定义注解—声明注解---得到注解。
A, 定义注解(参照上面的注解定义)
B, 声明注解
a) 在哪些元素上声明注解,
如果定义注解时没有指定@Target来限制注解的范围,那么该注解可以使用ElementType枚举指定任何一个元素前面,否则只能在@Target指定的元素前。
一般形式:@注解名()
2,对注解的方法的返回值进行赋值
对于注解中定义的每一个没有默认返回值的方法,在声明注解时必须对它的每一个方法的返回值进行赋值
一般形式:
@注解名(方法名=返回值,。。。)
如果方法返回的是一个数组时,那么将方法返回值写在{}符号里
@注解名(方法名={返回值1,返回值2、、、},、、、)
对于只含有value方法的注解,在声明注解时可以只写返回值。(如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员)
Eg:
/**
* 水果名称注解
* @author peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}
得到注解
对于生命周期为运行期间的注解,都可以通过反射获得该元素上的注解实例
- 声明一个类中的注解
a) 可以通过Class对象的getAnnotation 或者getAnnotations方法进行获得。
- 声明在一个字段中的注解
a) 可以通过Field对象的getAnnotation 或者getAnnotations方法进行获得。
- 声明在一个方法中的注解
a) 可以通过Method对象的getAnnotation 或者getAnnotations方法进行获得。
注解元素的默认值:
注解元素必须有确定的值,要么在定义注 解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具 有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法
/**
* 水果供应者注解
* @author peida
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/**
* 供应商编号
* @return
*/
public int id() default -1;
/**
* 供应商名称
* @return
*/
public String name() default "";
/**
* 供应商地址
* @return
*/
public String address() default "";
}
总结:
注解可以看成是一个接口,注解实例就是一个实现了该接口的动态代理类。
注解大多是用做对某个类、方法、字段进行说明,标识的。以便在程序运行期间我们通
过反射获得该字段或方法的注解的实例,来决定该做些什么处理或不该进行什么处理
解惑:
field.isAnnotationPresent(FruitColor.class)//field 为 Field的实例。
判断field字段是否使用了FruitColor这个注解。