一、为什么学习java注解?
java注解是在1.5时,才有的特性。对于安卓的开发者来说,可能用到注解的地方比较少,但我们也会涉及到一些常用的注解:比如:1、@Override当我们重写一个方法时,该注释表示这个方法是重写
2、@Deprecated在安卓中一些老版本SDK的方法会被丢弃
3、@SuppressWarnings表示去掉某个警告。
警告是分等级的:
deprecation 使用了过时的类或方法时的警告
unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型
fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
path 在类路径、源文件路径等中有不存在的路径时的警告
serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
finally 任何 finally 子句不能正常完成时的警告
all 关于以上所有情况的警告
unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型
fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
path 在类路径、源文件路径等中有不存在的路径时的警告
serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
finally 任何 finally 子句不能正常完成时的警告
all 关于以上所有情况的警告
但是在开发的过程中,我们并没有真正的去用过注释,也许你在gson中用到过。
java注释一般在java开发中用的比较多有依赖注入等框架,前两天看到Dagger2看到好多的都是和注解有关的,所以拿出点时间来学习下。
二、java注解的元注解
我们可以定义一个我们自己的注解:
<pre name="code" class="java"> public @interface MyAnotation {
}
什么是元注解?
@interface 后面的名称就是注解的名字,这就是一个简单的注解
所谓的元注解,就是可以注解我们自定义的注解的元注解。
以下都以我们自定义个这个MyAnotation为例来解释。
1、@Retention
@Retention(RetentionPolisy.RUNTIME)
public @interface MyAnotation {
}
在我们自定义的注解上注解Retention注解的话就会对我们的注解起到保留策略:是在源代码中,还是在class文件中,还是在运行中都可见。
分为以下三种类型:
①Retention.SOURCE仅在源代码中可见,在被MyAnotation注解的类编译后的class文件中是看不到我们的MyAnotation的注解的
②Retention.CLASS
在源代码和class中都可见,但是在运行时就不可见了,
③Retention.RUNTIME 在源代码,在class中,在运行时都是可见的,我们可以通过反射得到我们的MyAnotation
2、@Target
@Target(ElimentType.TYPE)
public @interface MyAnotation {
}
@Target(ElementType.TYPE)
// 注解我们的自定义注释后,我们的注释可以在接口、类、枚举、注解,上注释,不能应用于方法,局部变量等其他类型
@Target(ElementType.FIELD) // 字段、枚举的常量
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法参数
@Target(ElementType.CONSTRUCTOR) // 构造函数
@Target(ElementType.LOCAL_VARIABLE) // 局部变量
@Target(ElementType.ANNOTATION_TYPE) // 注解
@Target(ElementType.FIELD) // 字段、枚举的常量
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法参数
@Target(ElementType.CONSTRUCTOR) // 构造函数
@Target(ElementType.LOCAL_VARIABLE) // 局部变量
@Target(ElementType.ANNOTATION_TYPE) // 注解
复合的方式,比如我们想我们自定义的注释既能应用于类,又能应用于方法那么我们就这样写元注解
@Target(ElementType.TYPE,ElementType.METHOD)
3、@Document
@Document
public @interface MyAnotation {
}
这样我们的自定义注解MyAnotation在注视到一个类或者方法中,那么我们的注释在javadoc中是可以看到的4、@Inherited
子类可以继承父类中的注解
@Document
@Inherited
@Retention(RetentionType.RUNTIM)
@Target(ElementType.TYPE)
public @interface MyAnotation {
}
举例说明:
如果我们自定义注解在我们的一个类中如
我们自定义注解AnotationTest2
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface AnotationTest2 {
abstract String value() default "默认值";
}
@AnotationTest2(value="sss")
public class Test {
}
然后:TestImp继承Test类public class TestImp extends Test {
public void testImp(){
}
public static void main(String[] args){
try {
ParseAnnotation.parseType(TestImp.class);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
类ParseAnotation类public class ParseAnnotation {
public static void parseMethod(Class clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
for(Method method:clazz.getDeclaredMethods()){
AnotationTest1 anotation1 = method.getAnnotation(AnotationTest1.class);
if(anotation1!=null){
String value;
value = anotation1.value();
method.invoke(obj, value);
}
}
}
public static void parseType(Class clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
AnotationTest2 anotation2 = (AnotationTest2) clazz.getAnnotation(AnotationTest2.class);
if(anotation2!=null){
String value;
value = anotation2.value();
System.out.println("我的values:"+value);
}
}
}
如果AnotationTest2中的元注解有@Inherited的话,那么在子类TestImp中通过ParseAnotaion.parseType()方法就可以得到父类AnotationTest2的注解并获得注解中的值。如果我们去掉@Inherited的话,就获取不到Anotation的对象,anotation2为null。
三、自定义注解
在上面中我们已经涉及到自定义注解AnotationTest2。
我们除了为自定义注解设置元注解的属性外,我们还可以为自定义注解设置一些基本的属性。
@Inherited
public @interface Greeting {
String name() default "蓝色";
public enum FontColor{ BULE,RED,GREEN};
FontColor fontColor() default FontColor.GREEN;
}
name是我们为自定义注释Greeting添加变量,同时我们还可以为其设置
默认值
String
name();
如果我们没有设置默认值的话,那么在设置属性的时候必须为name属性设置值
自定义注解 中还可以定义枚举类型,并同时设置枚举的变量。