Java和Android中的注解

转载自  Java和Android中的注解

1.引言

从JDK1.5开始,引入了注解类Annotation,Annotation其实是一种接口,可以作用于类、方法、属性等等 ,它可以通过反射机制来访问annotation信息,获取所加上注解信息,做相应的操作。相当于给相关的作用对象打上“tag”,使用方便,作用广泛。

2.java.lang中的注解

     在java.lang中,用到三种注解类,即常用到的Deprecated,Override和SuppressWarnings.

     2.1 @Deprecated 过时

     在使用Eclipse或AS编写程序过程中,有一些方法编写出来之后被画上了中划线,表示该方法已过时,建议使用新的一些方法代替。
     如:viewPager.setOnPageChangeListener()方法在安卓API23中已过时,在源代码中的该方法上赫然多了一个注解@Deprecated,可使用addOnPageChangeListener()方法代替。
     如果使用javac命令编译,会弹出:”注意:使用或覆盖了已过时的API“

     2.2 @Override 复写

     这是开发过程中最常遇到的注解了,表示复写父类中的方法。如果方法上有这条注解但没有重写父类方法,则会生成一条错误消息。这个注解有效地保证了方法一定会被复写。比如开发过程中,手动在子类中复写父类方法,只正确写出了方法名称,未写正确方法的参数,则相当于方法的重载,并不是复写。这种问题如果在功能上有错误产生,在检查过程中是很难找到的。使用@Override注解,有效地表明,此方法是复写父类的方法,不会产生手动的错误问题。

     2.3 @SuppressWarnings 阻止警告

     阻止了弹出的警告,比如屏蔽对上述过时的提示,可在调用setOnPageChangeListener()方法之上加上@SuppressWarnings("deprecation"),这样虽然在IDE中仍以中划线的形式表示,但如果使用javac命令就不再提示警告。

3.元注解

     那么以上的注解类的源码又是什么样的呢,打开Override发现其代码如下

@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.SOURCE)  
public @interface Override {  
}  

这里可以发现注解类的定义方法以及注解类上所加的注解——元注解。元注解有四个,位于java.lang.annotation包中:Documented,Inherited,Retention,Target

     3.1@Target

     表示注解作用的目标。

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Target {  ElementType[] value();  
}  

注解可以作用的目标由枚举类ElementType决定,可作用于类、方法、属性等,数组表示注解可以有多个作用域。

public enum ElementType {  TYPE,// 类、接口、注解类型或枚举  FIELD, //属性  METHOD, //方法  PARAMETER,// 用于描述参数  CONSTRUCTOR,//构造方法  LOCAL_VARIABLE,//局部变量  ANNOTATION_TYPE,//注解类  PACKAGE //包  
} 

注解作用于类时,定义@Target(ElementType.TYPE),ElementType .TYPE表示类型,Class,Interface等都实现了java中的Type接口,因此ElementType.TYPE 表示注解作用于这些"类"(并不是单纯的Class类)

     3.2@Retention

     表示注解的作用时段

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Retention {  RetentionPolicy value();  
}  

由此可见,Retention定义的是RetentionPolicy类型的数据,RetentionPolicy是一个枚举类型,包括SOURCE,CLASS,RUNTIME三个类型。表示注解保留的阶段。
SOURCE:表示注解只在源文件中保留
CLASS:表示注解保留到.class文件中
RUNTIME:表示注解一直保留到内存中,类加载器把.class文件加载到内存中产生的字节码中要保留注解信息。
可想而知,@Override仅在写代码时用到,其Retention中的值为RetentionPolicy.SOURCE,@SuppressWarnings也只是编译器使用的,保留到SOURCE阶段。而@Deprecated在内存中也需要保留,编译器需要得知方法是否过时,从加载到内存中的二进制文件中获取,因而要保留到RUNTIME阶段


     3.3@Documented 

注解只是一个标记的话,那么使用javadoc生成文档时,这些注解都不会存在于文档中,要使注解在文档中也存在,就可以在使用了注解的作用对象上加上@Documented这个注解。javadoc所生成的文档就会带上注解信息。

     3.4@Inherited

该注解表示子类可以集成加载父类上的注解。但要注意:
1.注解定义在类上面,子类是可以继承该注解
2.注解定义在方法上面,子类也可以继承该注解,但是如果子类复写了父类中定义了注解的方法,那么子类将无法继承该方法的注解,也就是说,子类在复写父类中被@Inherited标注的方法时,会将该方法上面的注解覆盖掉
3.Interface的实现类(implements实现)无法继承接口中所定义的被@Inherited标注的注解

4.注解的参数

在注解后为注解增加参数,如上述的@Retention、@Target后的括号中就是注解的参数。
参数的类型,支持基本数据类型、String类型、Class类型、enum类型、Annotation类型以及上述所有类型的数组。
当注解只有一个参数时,可以用value作为参数名称,在使用参数时,只用在括号中写参数的值而不用写参数名称。若存在多个参数时,需写上对应的参数名,并赋值,如@Subscribe(tag="xx"),若参数为数组类型,则需赋值形如:@Target({ElementType.TYPE,ElementType.METHOD})

5.自定义注解

从上面的注解中,也大致看到了注解的定义方式。
1.使用@interface定义一个注解类,其内部自行继承了Annotation类。
2.在该类中定义注解的参数,定义方式很像方法。
3.注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。定义一些特殊的值,例如空字符串或者负数,表示某个元素不存在参数设置默认值时,后面跟上default即可设置默认值。
4.当注解的参数只有一个时,建议用value作为参数名,这样在使用注解时,可以直接写参数的值
接下来自定义一个注解类:
@Documented  
@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface Car{  String name() default "";  int number() default -1;  
}  
再定义一个类去使用这个注解:
@Car(name="好车",number=666)  
public class CarBMW(){  }
那么如何获取这些注解值呢?有如下的方法:
if(CarBMW.class.isAnnotationPresent(Car.class)){//判断CarBMW类是否有注解类Car  Car carAnnotation=(Car)CarBMW.class.getAnnotation(Car.class);//获取注解实例对象  Log.v("Shawn",carAnnotation.name());//获取name参数的值  Log.v("Shawn",carAnnotation.number());//获取number参数的值  
}  

5.1 JAVA8中注解的补充

在JAVA8中,增加了TypeAnnotation,在 Java 8 之前的版本中,只能允许在声明式前使用 Annotation。而在 Java 8 版本中,Annotation 可以被用在任何使用 Type 的地方,例如:初始化对象时 (new),对象类型转化时。

//初始化对象时  
String myString = new @NotNull String();  
//对象类型转化时  
myString = (@NonNull String) str;
这点上有点类似Android中的注解使用。
而ElementType中增加了俩个值ElementType. T YPE_PARAMETER 和ElementType. TYPE_USE  正是为此功能实现而产生的。
ElementType. TYPE_PARAMETER  表示这个 Annotation 可以用在 Type 的声明式前,而 ElementType .TYPE_USE  表示这个 Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)。
Type Annotation 也可以通过设置 Retention 在编译后保留在 class 文件中(RetentionPolicy.CLASS)或者运行时可访问(RetentionPolicy.RUNTIME)。但是与之前不同的是,Type Annotation 有两个新的特性:在本地变量上的 Annotation 可以保留在 class 文件中,以及泛型类型可以被保留甚至在运行时被访问。
此外,JAVA8中还增加了一个特性RepeatingAnnotation,允许为同一个声明式或者类型加上相同的 Annotation。

例如:一个类可以被两个人使用:

@Worker(role="XiaoMing")  
@Worker(role="XiaoHong")  
public class Person {  ...  
} 

需要需要重复标注特性的 Annotation 前加上 @Repeatable 标签

@Repeatable(Workers.class)  
public @interface Worker{  String role();  
}  
@Repeatable 标签后括号中的值即为指定的 Container Annotation 的类型。在这个例子中,Container Annotation 的类型是 Workers,Java 编译器会把重复的 Worker 对象保存在 Workers中。

Workers中必须定义返回数组类型的value()方法。数组中元素的类型必须为对应的 Repeating Annotation 类型。具体示例如下:

public @interface Workers{  Worker[] value();  
}  
获取注解的方法有两种:

一种方式是用过 上述的的 getAnnotations(Class<T>) 方法一次性返回 Repeating Annotation。

另一种方式是通过 AnnotatedElement 接口的 getAnnotationByType(Class<T>) 首先获得 Container Annotation,然后再通过 Container Annotation 的 value 方法获得 Repeating Annotation。

Workers workers= Person.class.getAnnotation(Workers.class);  
Worker[] workers2= Person.class.getAnnotationsByType(Worker.class);  
以上关于JAVA8中的注解参考 http://www.ibm.com/developerworks/cn/java/j-lo-java8annotation/index.html

6.Android中的注解

6.1两个常见的注解

Android从API16引入了annotation包,包括两个注解@TargetApi和@SuppressLint
@TargetApi (Build.VERSION_CODES.XX)用于屏蔽某一新api中才能使用的方法报的lint检查出现的错误。
@SuppressLint("NewApi") 屏蔽一切新api中才能使用的方法报的android lint错误

当然,这两个注解的作用仅仅是屏蔽lint错误,在方法中还要判断版本做不同的操作,比如:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XX) {  //高于XX版本进行的操作  
} else {  //低于XX版本进行的操作  
}  

6.2Android中用到的注解

API19引入了很多注解,起初是以jar包形式引入的,放在SDK目录下sdk\extras\android\m2repository\com\android\support\support-annotations\
在API21之后,直接放入了annotation包中
Android中的注解分为八类,在API23中有42个注解类

6.2.1 @CallSuper

要求方法必须调用父类方法,可想而知,Activity的onCreate()方法有此注解标识。

6.2.2 @NonNull和@Nullable     

定义一个变量或对象可以为空或不可为空,用在方法上表示方法可否返回空。

6.2.3 资源类注解

@AnimatorRes,@AnimRes,@AnyRes,@ArrayRes,@AttrRes,@ BoolRes,@ ColorRes,@ DimensRes,@ DrawableRes,@ FractionRes,@ IdRes,@ IntegerRes,@ InterpolatorRes,@ LayoutRes,@ MenuRes,@ PluralsRes,@ RawRes,@ StringRes,@ StyleableRes,@StyleRes,@ TransitionRes,@ XmlRes
这部分注解是非常有实用性的,有22个,用法如:
getDrawable(@DrawableRes int id)  //getDrawable方法限定了传入的参数必须是Drawable资源文件 
另外还有个@ColorInt,限制传入Hex颜色值。
在开发过程中需要传入某种资源文件时,用此类注解,是很有限制作用的做法。

6.2.4@IdDef和@StringDef

提到最常用的Toast,在API21之前,一般可以这么写
Toast.makeText(context, "msg", 0).show();
但是21之后,0突然被划红线了,查看源码发现,之前是这么写的:
public static final int LENGTH_SHORT = 0;  
public static final int LENGTH_LONG = 1;  
makeText方法中单纯地写着int duration参数,而21之后,成了这样:
@IntDef({LENGTH_SHORT, LENGTH_LONG})  
@Retention(RetentionPolicy.SOURCE)  
public @interface Duration {}  
在makeText的duration参数之前加上了注解@Duration,这就要求传入Duration中的值才不会报警告。
可以想象,@IntDef和@String Def中放入了一个value数组。
在开发中,这两个注解就可以用来限制枚举值了。

6.2.5 范围约束@FloatRange、@IntRange和@Size

前两个限制了数字的范围,比如可以用来限制传入参数值的范围,
@Size可以用来限定集合的大小或者限定字符串的长度,还可以做其他限制:
1.限制最小最大数量:@Size(min=1,max=10 )
2.数量必须是2的倍数(偶数): @Size(multiple=2)

6.2.6 进程类注解

@UiThread,@BinderThread,@MainThread,@WorkerThread
用来限定方法或类在指定的线程类型中被调用,比如 AsyncTask中的方法就有如下的限定:
@WorkerThread  
protected abstract Result doInBackground(Params... params){  //doInBackground  
}  
@MainThread  
protected void onProgressUpdate(Progress... values) {  //onProgressUpdate  
}  

6.2.7@CheckResult

该注解意味着需要对方法的返回值进行处理,例如:有个方法为
@CheckResult  
public boolean checkValid(String value){  return TextUtils.isEmpty(value);  
}  
当调用者直接调用checkValid("abc");时会报错,这意味着,需要对方法的返回值进行处理,无论返回true或false,需要进行后续操作,不能单单调用一句checkValid("abc");

6.2.8 权限注解@RequiresPermission

如果方法的调用需要权限,可以加这个注解,当需要几个权限中的一个时,使用anyOf,如 @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})
若需要多个权限,使用allOf,如 @RequiresPermission(allOf = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
若需要单独的标注读和写的权限访问,所以可以用@Read或者@Write标注每一个权限需求

6.2.9 @SdkConstant

表示一个常量字段应该被输出在SDK工具中使用,例如:
添加一个自定义的Action:
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)   
public static final String ACTION_MY_TEST = "android.intent.action.MY_TEST";  
则可以这样使用:
Intent myTest = new Intent(Intent.ACTION_MY_TEST);   
mContext.sendBroadcast(myTest);  


6.2.10@Widget

用于类的注解,表示该类是自定义的Widget类

此外还有两个注解即上述的@TargetApi和@SuppressLint不再赘述。

7.总结

综上,注解部分就介绍完了。注解在开发过程中有很强的实用性,使用注解可以明确开发过程中的一些数据类型,还可以对一些数据进行限制,从而提高开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二章 指南(4.3)添加 View

原文&#xff1a;Adding a view作者&#xff1a;Rick Anderson翻译&#xff1a;魏美娟(初见)校对&#xff1a;赵亮(悲梦)、高嵩(Jack)、娄宇(Lyrics)、许登洋(Seay)、姚阿勇&#xff08;Dr.Yao&#xff09; 本节将修改 HelloWorldController 类&#xff0c;把使用 Razor 视图模…

java多表查询返回数据_spring data jpa如何在多张数据库表中查询返回某些字段值?...

对于多表联查需要使用springdata jpa的Query标注实现&#xff0c;例如最代码的我的私信列表的查询&#xff1a;public static final String POSTREPOSITORY_FINDALLBYTYPEANDGROUPBYUSERID "select id from (select id,target_id,case when user_id?1 and type?2 then …

JAVA反射修改常量,以及其局限

转载自 JAVA反射修改常量&#xff0c;以及其局限问题&#xff0c;以及一个解决方案 今天公司的JAVA项目碰到一个问题&#xff1a;在生成xls文件的时候&#xff0c;如果数据较多&#xff0c;会出现ArrayIndexOutOfBoundsException。Google发现是项中所用的jxl包&#xff08;开源…

java出代码1601_LeetCode 1601. 最多可达成的换楼请求数目

题目描述我们有 n 栋楼&#xff0c;编号从 0 到 n - 1 。每栋楼有若干员工。由于现在是换楼的季节&#xff0c;部分员工想要换一栋楼居住。给你一个数组 requests &#xff0c;其中 requests[i] [fromi, toi] &#xff0c;表示一个员工请求从编号为 fromi 的楼搬到编号为 toi …

asp.net core 中间件详解及项目实战

前言 在上篇文章主要介绍了DotNetCore项目状况&#xff0c;本篇文章是我们在开发自己的项目中实际使用的&#xff0c;比较贴合实际应用&#xff0c;算是对中间件的一个深入使用了&#xff0c;不是简单的Hello World&#xff0c;如果你觉得本篇文章对你有用的话&#xff0c;不妨…

一分钟实现分布式锁

转载自 一分钟实现分布式锁一、缘起 分布式环境下&#xff0c;多台机器上多个进程对一个数据进行操作&#xff0c;如果不做互斥&#xff0c;就有可能出现“余额扣成负数”&#xff0c;或者“商品超卖”的情况&#xff0c;如何实现简易分布式锁&#xff0c;对分布式环境下的临界…

java建立线性表的链式结构_Java实现线性表的链式存储

本文实例为大家分享了Java实现线性表的链式存储&#xff0c;供大家参考&#xff0c;具体内容如下链表&#xff1a;一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。package algorithm.datastructure.linklist;import java.ut…

dotnet core 开发体验之Routing

开始 回顾上一篇文章&#xff1a;dotnet core开发体验之开始MVC 里面体验了一把mvc,然后我们知道了aspnet mvc是靠Routing来驱动起来的&#xff0c;所以感觉需要研究一下Routing是什么鬼。 Routing简单使用体验 首先我们用命令yo aspnet创建一个新的空web项目。&#xff08;Yeo…

线程间协作的两种方式:wait、notify、notifyAll和Condition

转载自 线程间协作的两种方式&#xff1a;wait、notify、notifyAll和Condition在前面我们将了很多关于同步的问题&#xff0c;然而在现实中&#xff0c;需要线程之间的协作。比如说最经典的生产者-消费者模型&#xff1a;当队列满时&#xff0c;生产者需要等待队列有空间才能继…

格密码基础:q-ary格

目录 一. 格密码的重要性 二. 格密码基础 2.1 格点的另一种理解方式 三. q-ary格 3.1 q-ary垂直格 3.2 q-ary格 3.3 二者结合 四. 论文中的q-ary格 4.1 定理1 4.2 定理2 4.3 定理3 一. 格密码的重要性 格密码的基础是研究格点上的困难问题&#xff0c;这种格点使用…

java动脑公开课_java课堂动手动脑

实验任务一&#xff1a;阅读并运行示例PassArray.java.1)源代码&#xff1a;package demo;//PassArray.java//Passing arrays and individual array elements to methodspublic class PassArray {public static void main(String[] args) {int a[] { 1, 2, 3, 4, 5 };String o…

dotnet core开发体验之开始MVC

开始 在上一篇文章&#xff1a;dotnet core多平台开发体验 &#xff0c;体验了一把dotnet core 之后&#xff0c;现在想对之前做的例子进行改造&#xff0c;想看看加上mvc框架是一种什么样的体验&#xff0c;于是我就要开始诞生今天的这篇文章来分享我的感受了。 一、项目改造加…

Java时间处理第三方包:Joda-Time

转载自 Java时间处理第三方包&#xff1a;Joda-TimeJoda-Time provides a quality replacement for the Java date and time classes.Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (…

Visual Studio Code五月版本更新

开源项目、跨平台代码编辑器Visual Studio Code刚发布了其1.2版本&#xff08;虽然说是2016年5月发布&#xff0c;但其实是在6月交付的&#xff09;。和往常一样&#xff0c;这次发布的版本中对于很大一部分功能都进行了改善&#xff0c;其中最值得关注的可能是一种全新整合的终…

关于SimpleDateFormat时间格式化线程安全问题

转载自 关于SimpleDateFormat时间格式化线程安全问题昨天推送的文章《关于创建和销毁对象》一文中&#xff0c;2.1重复利用对象这一小节所举的SimpleDateFormat格式化时间的例子是不合适的&#xff0c;因为多线程场景下&#xff0c;SimpleDateFormat存在线程安全问题。在此&am…

聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer

跨平台是ASP.NET Core一个显著的特性&#xff0c;而KestrelServer是目前微软推出了唯一一个能够真正跨平台的Server。KestrelServer利用一个名为KestrelEngine的网络引擎实现对请求的监听、接收和响应。KetrelServer之所以具有跨平台的特质&#xff0c;源于KestrelEngine是在一…

pdfbox java.lang.outofmemoryerror_Apache PDFBox 1.8.11 发布,Java 的 PDF 处理类

Apache PDFBox 1.8.11 发布&#xff0c;此版本是个增量 bug 修复版本&#xff0c;包括大量 bug 修复和改进。现已提供下载&#xff1a;主要改进内容&#xff1a;Bug 修复[PDFBOX-962] - All sort of Problems when importing Xfdf files into PDFs ->damaged pdfs and NPEs[…

Java8 Striped64 和 LongAdder

转载自 Java8 Striped64 和 LongAdder 数据 STRIPING 根据维基百科的这段说明&#xff1a;In computer data storage, data striping is the technique of segmenting logically sequential data, such as a file, so that consecutive segments are stored on different phys…

Roslyn项目系统简介

发布15年后&#xff0c;Microsoft终于开始替换Visual Studio中基于COM的C#和Visual Basic项目系统。Microsoft谈及很多有必要放弃目前所用系统的原因&#xff1a; 原生且基于COM单线程并与UI线程绑定难以通过和&#xff08;不同用途的&#xff09;子类型类扩展到聚合之外与Visu…

fastdfs 集群 java_FastDFS集群部署(转载 写的比较好)

之前介绍过关于FastDFS单机部署&#xff0c;详见博文&#xff1a;FastDFSNginx(单点部署)事例下面来玩下FastDFS集群部署&#xff0c;实现高可用(HA)服务器规划&#xff1a;跟踪服务器1【主机】(Tracker Server)&#xff1a;192.100.139.121跟踪服务器2【备机】(Tracker Server…