API开发文档:https://developer.android.com/studio/write/annotations.html
注解
注解是一种元数据, 可以添加到java代码中. 类、方法、变量、参数、包都可以被注解,可用来将信息元数据与程序元素进行关联,注解对注解的代码没有直接影响.
注解库
如果你使用了com.android.support:appcompat-v7库不需要添加额外的依赖。
但是如果你没有使用这个库,也可以额外单独添加注解库。compile 'com.android.support:support-annotations:xx.xx.xx'。
注解的作用
便于生成文档。
用于编译时的检查。
用于简洁化代码。
一:标准 Annotation
Nullness注解
@Nullable
@NonNull
/** Add support for inflating the tag. **/
@NonNull
@Override
public View onCreateView(String name, @NonNull Context context,
@NonNull AttributeSet attrs) {
}
资源类型的注解
public abstract void setTitle(@StringRes int resId) { … }
资源类型的注解,有以下几种:
@StringRes
@ColorRes
@AnimationRes
@DimensionRes
@DimensionPixelOffsetRes
@DimensionPixelSizeRes
@BooleanRes
@ColorStateListRes
@DrawableRes
@IntArrayRes
@IntegerRes
@LayoutRes
@MovieRes
@TextRes
@TextArrayRes
@StringArrayRes
Thread 注解
@MainThread
@UiThread
@WorkerThread
@BinderThread
@AnyThread
值约束注释
@IntRange
public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }
@FloatRange
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
@Size
最大值 (such as @Size(min=2))
最小值(such as @Size(max=2))
限定值 (such as @Size(2))
int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);
Permission 权限注解
对于有些方法可能需要系统的一些权限,但是我们会忘了在Manifest中加入这些权限,导致程序报错。
例如:
单个权限:
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;```
例如存储卡权限(多个权限)
@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) { ...}
对于Intent权限限制,在需要权限的action中添加权限:
@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
对于ContentProviders 需要区分read和write权限,可以采用[@RequiresPermission.Read ](https://developer.android.com/reference/android/support/annotation/RequiresPermission.Read.html)或者 [@RequiresPermission.Write ](https://developer.android.com/reference/android/support/annotation/RequiresPermission.Write.html)
注解如下:
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
直接添加权限:
[startActivity(Intent)](https://developer.android.com/reference/android/app/Activity.html#startActivity(android.content.Intent))
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}```
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";
返回值注解
@CheckResult
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
强制super注解
比如我们写一个基类:
public class Base {
@CallSuper
public void test(){
Log.e("","");
}
}```
##Typedef 类型注解
[@IntDef](https://developer.android.com/reference/android/support/annotation/IntDef.html)
[@StringDef](https://developer.android.com/reference/android/support/annotation/StringDef.html)
IntDef StringDef可以限制传入参数的内容,这在一些固定参数的方法中尤为重要
public abstract class ActionBar {
...
// Define the list of accepted constants and declare the NavigationMode annotation
@Retention(RetentionPolicy.SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
// Declare the constants
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
// Decorate the target methods with the annotation
@NavigationMode
public abstract int getNavigationMode();
// Attach the annotation
public abstract void setNavigationMode(@NavigationMode int mode);
##@keep
[@Keep](https://developer.android.com/reference/android/support/annotation/Keep.html)
一看到这个词肯定第一反应就是跟混淆相关的,没错,这个就是标识该方法被keep出来,当然你也可以在混淆文件中keep
#二:元注解
Override注解的源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}```
元注解就是用来定义注解的注解.其作用就是定义注解的作用范围, 使用在什么元素上等等, 下面来详细介绍.
元注解共有四种
- @Documented –注解是否将包含在JavaDoc中
- @Retention –什么时候使用该注解
- @Target –注解用于什么地方
- @Inherited – 是否允许子类继承该注解
@Retention
@Retention 保留的范围,默认值为CLASS. 可选值有三种
SOURCE, 只在源码中可用
CLASS, 在源码和字节码中可用
RUNTIME, 在源码,字节码,运行时均可用
- RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
- RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
- RetentionPolicy.RUNTIME – 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
@Target
@Target 可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER等,未标注则表示可修饰所有
- 取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Inherited
@Inherited 是否可以被继承,默认为false
@Documented
@Documented 是否会保存到 Javadoc 文档中
其中, @Retention是定义保留策略, 直接决定了我们用何种方式解析. SOUCE级别的注解是用来标记的, 比如Override, SuppressWarnings. 我们真正使用的类型是CLASS(编译时)和RUNTIME(运行时)
三:自定义注解
自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation
这里是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
定义注解格式:
public @interface 注解名 {定义体}
注解参数的可支持数据类型:
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
Annotation类型里面的参数该怎么设定:
- 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;
- 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;
- 第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。
注意:
- 注解可以设定初始值,使用default就可以实现。
注解只有一个元素的时候,该元素名称必须是value,并且在使用该注解的时候可以省略”alue=”。
注解的值必须是确定的,且不能使用null作为值。
注解可能的类型:所有基本类型、String、Class、enum、Annotation、以上类型的数组形式。
举个例子
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
String value();
String[] value2() default "value2";
}```
元注解的的意义参考上面的讲解, 不再重复, 这里看注解值的写法:
类型 参数名() default 默认值;
其中默认值是可选的, 可以定义, 也可以不定义
* 自己写的例子:
自定义一个注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD ,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String isAop() default "false";
}
通过反射机制获取:
public class TestProcess {
public static void process(String str) throws ClassNotFoundException {
Class clazz = Class.forName(str);
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation.);
}
}
}
测试使用:
@Test(isAop = "false")
public class UseTest {
public static void main(String[] args) {
try {
TestProcess.process("Test");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
###参考链接:
>[公共技术点之 Java 注解 Annotation](http://a.codekk.com/detail/Android/Trinea/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20Java%20%E6%B3%A8%E8%A7%A3%20Annotation)
[[自定义注解定义和使用](http://blog.csdn.net/u012150370/article/details/47304435)](http://blog.csdn.net/u012150370/article/details/47304435)