两种注解的基本使用
来源:互联网 发布:杭州网络推广营销 编辑:程序博客网 时间:2024/06/04 19:07
首先介绍下注解的基本知识,详细使用方法请自行百度
首先注解分为三类:
标准 Annotation,元 Annotation,自定义 Annotation
(1).标准 Annotation
包括 Override, Deprecated, SuppressWarnings,是java自带的几个注解,他们由编译器来识别,不会进行编译,
不影响代码运行,至于他们的含义不是这篇博客的重点,这里不再讲述。
(2).元 Annotation
@Retention, @Target, @Inherited, @Documented,它们是用来定义 Annotation 的 Annotation。也就是当我们要自定义注解时,需要使用它们。
(3).自定义 Annotation
根据需要,自定义的Annotation。而自定义的方式,下面我们会讲到。
同样,自定义的注解也分为三类,通过元Annotation - @Retention 定义:
@Retention(RetentionPolicy.SOURCE)
源码时注解,一般用来作为编译器标记。如Override, Deprecated, SuppressWarnings。
@Retention(RetentionPolicy.RUNTIME)
运行时注解,在运行时通过反射去识别的注解。
@Retention(RetentionPolicy.CLASS)
编译时注解,在编译时被识别并处理的注解
这里主要介绍下运行时注解,和编译时注解。
所谓运行时注解是指,注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;所以注解信息会加入到class文件中,在使用的时候通过反射方法拿到注解的传递数值.这就是为什么说,使用注解会影响性能,就是因为使用了反射。下面通过一个简单例子进行解释说明。
编写注解,含有名字name,年龄age ,年龄设置有默认值10
@Target({ElementType.TYPE,ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Deanitation { String name(); int age() default 10;}
@Retention(RetentionPolicy.RUNTIME)表示该注解是运行时注解,@Target({ElementType.TYPE,ElementType.FIELD, ElementType.METHOD})表示该注解能作用的范围,
在类中使用方法如下:
@Deanitation(name ="test")public class Test { @Deanitation(name = "run",age = 17) public void run(){ System.out.print("run"); }}
然后在Main方法执行过程中通过反射获取注解标注的信息:
public static void main(String[] args) { try { Class c=Class.forName("com.zhujie.Test"); //2.判断类上是否存在注解,并获取类上面注解的实例 if(c.isAnnotationPresent(Deanitation.class)){ Deanitation Description = (Deanitation) c.getAnnotation(Deanitation.class); System.out.println(Description.name()); System.out.println(Description.age()); } //3.判断方法上是否存在注解,并获取方法上面注解的实例 Method[] ms = c.getMethods(); for (Method method : ms) { if(method.isAnnotationPresent(Deanitation.class)){ Deanitation Description = (Deanitation)method.getAnnotation(Deanitation.class); System.out.println(Description.name()); System.out.println(Description.age()); } } //另一种获取方法上的注解的解析方法 for (Method method : ms) { Annotation[] as = method.getAnnotations(); for (Annotation annotation : as) { if(annotation instanceof Deanitation){ System.out.println(((Deanitation) annotation).name()); System.out.println(((Deanitation) annotation).age()); } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
以上就是运行时注解使用的基本方法,应为在使用过程中使用反射,所以对性能有影响,使用范围也有限制。下面模拟ButterKnife的使用过程,说明下编译时注解的使用。
建立项目后,因为要继承AbstractProcessor编写自定义注解解释器,所以要建立一个javalib的module,在改module下编写注解类DebindVeiw
@Retention(RetentionPolicy.CLASS)@Target(ElementType.FIELD)public @interface DeBindView { int value();}
下面编写自定义注解解释器,主要是继承AbstractProcessor重写process方法,其中核心步骤是获取注解集合,然后生成所需要的java文件
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { messager.printMessage(Diagnostic.Kind.NOTE, "process..."); mProxyMap.clear(); Set<? extends Element> elesWithBind = roundEnv.getElementsAnnotatedWith(DeBindView.class); for (Element element : elesWithBind) { checkAnnotationValid(element, DeBindView.class); VariableElement variableElement = (VariableElement) element; //class type TypeElement classElement = (TypeElement) variableElement.getEnclosingElement(); //full class name String fqClassName = classElement.getQualifiedName().toString(); messager.printMessage(Diagnostic.Kind.NOTE, fqClassName); ProxyInfo proxyInfo = mProxyMap.get(fqClassName); if (proxyInfo == null) { proxyInfo = new ProxyInfo(elementUtils, classElement); mProxyMap.put(fqClassName, proxyInfo); } DeBindView bindAnnotation = variableElement.getAnnotation(DeBindView.class); int id = bindAnnotation.value(); /**获取View iD**/ proxyInfo.injectVariables.put(id, variableElement); } /** * 生成所需要的java类 */ for (String key : mProxyMap.keySet()) { ProxyInfo proxyInfo = mProxyMap.get(key); try { JavaFileObject jfo = processingEnv.getFiler().createSourceFile( proxyInfo.getProxyClassFullName(), proxyInfo.getTypeElement()); Writer writer = jfo.openWriter(); writer.write(proxyInfo.generateJavaCode()); writer.flush(); writer.close(); } catch (IOException e) { error(proxyInfo.getTypeElement(), "Unable to write injector for type %s: %s", proxyInfo.getTypeElement(), e.getMessage()); } } return true; }
下面生成的java文件
当然还要编写使用的API,我们要新建一个android lib module 在里面编写一个注册类,通过反射初始化 生成的类。达到初始化view findviewById()作用。
public class ViewInjector { private static final String SUFFIX = "$$ViewInject"; public static void injectView(Activity activity) { ViewInject proxyActivity = findProxyActivity(activity); proxyActivity.inject(activity, activity); } public static void injectView(Object object, View view) { ViewInject proxyActivity = findProxyActivity(object); proxyActivity.inject(object, view); } private static ViewInject findProxyActivity(Object activity) { try { Class clazz = activity.getClass(); Class injectorClazz = Class.forName(clazz.getName() + SUFFIX); return (ViewInject) injectorClazz.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } throw new RuntimeException(String.format("can not find %s , something when compiler.", activity.getClass().getSimpleName() + SUFFIX)); }}
使用方法如下:
@DeBindView(R.id.tv_text) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_annotation); ViewInjector.injectView(this); }
以上就是简单的使用编译时注解,完成时间绑定,详细代码请下载查看,包含annotationapi ,javalib 两个module,其中annotationapi 依赖javalib 。使用的时候导入module 主module app只需要依赖annotationapi就可以了
下载地址:点击
- 两种注解的基本使用
- 注解的基本使用
- CURL的两种基本使用
- CURL的两种基本使用
- JPA的注解的基本使用
- spring的基本注解使用demo
- 两种基本的数据结构
- Spring AOP 使用注解的方式实现用户日志的两种方法
- 使用spring4.0和4.1注解返回json格式的数据的两种实现方式
- jQuery-easyUI的使用:基本组件的使用、使用组件的两种方式
- Java的基本注解
- JPA的基本注解
- TestNG的基本注解
- junit4的基本注解
- TestNG的基本注解
- 黑马程序员---java几个基本的注解的使用
- 使用注解方式配置 AOP 的基本步骤(复习)
- [Android]_[注解库butterknife的基本使用]
- 5.rm — 删除文件或目录
- LeetCode--Remove Duplicates from Sorted List II
- 小猪的C语言快速入门系列(七)
- 模拟斗地主发牌看牌
- 移动云Apsara Mobile震撼发布!推出Cloud Native App全新研发范式
- 两种注解的基本使用
- 6.mv — 移动文件或改名
- ARP报文格式
- Visitor Design Pattern
- MYSQL基本命令
- (006) java后台开发之基本数据类型
- Apriori
- 7.cp — 将源文件复制至目标文件,或将多个源文件复制至目标目录
- hashmap