Java入门篇——注解Annotation
来源:互联网 发布:淘宝招聘官网首页 编辑:程序博客网 时间:2024/05/01 17:36
在Java1.5以后,引入了注解,也称作元数据。作为新的特性,同时也是基础知识之一,我们应该学会使用这种用法,虽然反射会带来代码效率问题,但相比于它的优点,这种损失我们还是可以承受的。
元数据被定义为:描述数据的数据,对数据及信息资源的描述性信息。
我们可以认为注解的目的就是对数据添加的附加信息。在java源代码中添加注解,有助于减轻编写“样板”代码的负担(findViewById),更加干净易读的代码以及编译器类型检查。
注解的语法比较简单,使用一个@符号修饰代表的就是一个注解。Java 5内置的几种注解有
//当前的方法定义将覆盖超类中的方法@Override//代表被这个元数据修饰的元素已被废弃,使用已废弃的方法或对象编译器会发出警告@Deprecated//关闭不当的编译器警告信息,比如unchecked,未检查的类型等@SuppressWarnings
自定义注解类型
使用@interface来定义注解类型
public @interface Test {}
使用注解类型
//一般写法,比较优美@Testvoid test(){}//注解可以看做是一种修饰符,它的使用和修饰符几乎一模一样// 不太好看,不建议public static synchronized @Test void test(){}
上面简单定义了一个注解,但是一般我们定义的注解,还会定义一些注解的类型,Annotation有四种元注解类型,元注解专职负责注解其他的注解,详情可以看Java API里面的Annotation
# Retention @Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Retention { RetentionPolicy value();}# Target @Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Target { ElementType[] value();}# Documented@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Documented {}# Inherited @Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Inherited {}
Rentention
Rentention定义该注解在哪一个级别保留该注解信息,可选的RetentionType参数包含
// 存在于Java源文件,注解被编译器丢弃SOURCE// 存在于Java源文件,以及经编译器后生成的Class字节码文件,但在运行时VM不再保留注解CLASS// 存在于源文件、编译生成的Class字节码文件,以及保留在运行时VM中,因此可通过反射读取注解RUNTIME
Target
Target表示该注解可以用于什么地方,可能使用的参数ElementType包括
// 注解类型,表示这个注解只能用于注解类型// 比如Target,Rentention,Inherited,Documented这些元注解都是用于注解类型的ANNOTATION_TYPE// 构造器声明CONSTRUCTOR// 字段声明(包括enum实例)FIELD// 局部变量声明LOCAL_VARIABLE// 方法声明METHOD// 包声明PACKAGE// 参数声明PARAMETER// 类,接口(包括注解类型)或者enum声明TYPE
Documented
当前注解的元素会被javadoc工具进行文档化,那么在查看Java API文档时可查看该注解元素。
Inherited
允许子类继承父类中的注解
注解元素
在注解中还会包含一些元素表示值,当使用Class里面的方法分析处理注解的时候,程序就可以访问这些值。在注解中定义元素就像在普通接口中定义方法,但是注解可以使用default定义元素的默认值。对于没有元素的注解,我们可以把它作为标记来使用。比如被@Test标记的方法为测试方法
注解元素可用的类型包括如下几个
基本数据类型StringClassenumAnnotation以上类型的数组
对于注解里面的元素,必须有一个确定的值,不能够使用null这种未定义的值作为默认值,所以我们可以使用空对象这样的概念来解决这个问题,比如定义空字符串作为字符串为null的情况。
解析注解
在很多ORM数据库框架中都使用了注解来定义Bean类,直接使用Bean类生成数据库表。比如ORMLite。
如果不对注解进行解析的话,其实注解就没什么意义了,可以通过Annotation中提供的API来访问注解。那么先来看一下Class提供给我们的用于解析注解的结构方法
// 如果当前元素包含指定的注解类型,则返回该注解对象,如果不存在则返回null<A extends Annotation> getAnnotation(Class<A> annotationClass)// 返回这个元素上的所有注解Annotation[] getAnnotations()// 返回直接定义在这个元素上的注解Annotation[] getDeclaredAnnotations()// 如果当前这个元素包含指定的注解类型则返回trueboolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
在Android中也有通过注解实现的IOC,我们在编写程序的时候,如果xml里面有很多很多的控件,这样就需要写很多遍findViewById,不但写起来很累,而且很占空间,于是人们就想到了通过注解来减轻这样的编写“样板”代码的负担。
ViewInject注解类
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ViewInject { int id() default -1;}
BaseActivity基类,使用模板方法
public abstract class BaseActivity extends Activity { private Context mContext; private void inject() { Class activity = getClass(); //获取Activity内所有的字段 Field[] fields = activity.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); // 获取指定的注解类型,如果返回null则跳过 ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) { // 获取指定的属性 int value = viewInject.id(); try { // 反射获取findViewById方法 Method method = activity.getMethod("findViewById", int.class); method.setAccessible(true); // 调用该方法,因为findViewById要求是在Activity对象上的方法 Object object = method.invoke(mContext, value); field.set(mContext, object); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } protected abstract int requestLayout(); protected abstract void bindView(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(requestLayout()); mContext = this; inject(); bindView(); }}
MainActivity实现类
public class MainActivity extends BaseActivity { @ViewInject(id=R.id.text) private TextView textView; @Override protected int requestLayout() { return R.layout.layout_annotation; } @Override protected void bindView() { textView.setText("1131"); }}
现在大致上那些retrofit,dagger,butterknife使用的注解也是基于这个原理的罢,有空去好好研究一下这几个开源框架的源码,使用注解,我们应该还需要有类加载,泛型,反射等基础知识,才能够把注解玩的飞起。
- Java入门篇——注解Annotation
- JAVA 注解Annotation入门
- Java——注解Annotation
- java 自定义注解(Annotation)入门
- Java-基本注解入门(Annotation)
- 深入理解Java:注解(Annotation)(二)——自定义注解入门
- Java:注解(Annotation)自定义注解入门
- Java注解 (Annotation)自定义注解入门
- Java:注解(Annotation)自定义注解入门
- JAVA 注解(Annotation)自定义注解入门
- java注解(Annotation)自定义注解入门
- java 注解(Annotation)自定义注解入门
- Java注解(Annotation)自定义注解入门
- Java注解(Annotation)自定义注解入门
- 黑马程序员——Java注解(Annotation)
- Java —— Annotation(注解)
- Java Annotation —— 注解基础
- Java Annotation —— 注解实战
- C语言中常用的几个内存申请函数
- 记录Android开发中使用HorizontalScrollView的坑
- 欢迎使用CSDN-markdown编辑器
- 3月24号
- 程序员的工作、学习与绩效
- Java入门篇——注解Annotation
- Office Web Apps Server作为Client,Java代码作为Host实现Office在线预览'
- c# in unity Update()函数的意义
- 全面解析回溯法:算法框架与问题求解
- javaScript的arguments传参数
- BFS in Graph and BFS in Matrix
- Android JNI编程
- JAVA学习之集合总结
- C++——STL之Map