Java编程思想学习笔记——注解
前言
在Android开发的过程中,我们为了减少重复代码的编写,会使用类似ButterKnife,AndroidAnnotations
这类依赖注解库。代码示例如下:
//不使用
Button btn = (Button)findViewById(R.id.btn);
//使用ButterKnife
@Bind(R.id.btn)
Button btn;
//使用AndroidAnnotations
@ViewById(R.id.btn)
Button btn;
可以看出通过注解,我们能大量减少啰嗦的声明和强转类型的代码的编写。
通过本篇文章的学习,对注解有个基本的认识和了解。
正文
1.什么是注解
注解(也叫元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。
2.注解的优点
- 1.可以提供用来完整地描述程序所需的信息(这些信息无法用Java表达)-> 以将由编译器来测试和验证的格式存储有关程序的额外信息。
- 2.可以用来生成描述符文件或是新的类的定义->减轻编写"样板"代码的负担
- 3.更加干净易读的代码以及编译器类型检查
3.注解的语法
@符号的使用,其他和Java固有语法一样
Java SE5内置了三种,定义在java.lang中的注解:
@Override 当前的方法定义将覆盖父类(超类)中的方法。
@Deprecated 被注解的元素被取代,不推荐使用( http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/deprecation/deprecation.html)
@SuppressWarnings 关闭不当的编译器警告信息
Java提供四种注解,专门负责新注解的创建。这种注解叫做元注解。
- 1.@Target 表示该注解可以用于什么地方。
ElementType参数包括:
public enum ElementType {
//类、接口(包括注解类型)或是enum声明
TYPE,
//域声明(包括enum实例)
FIELD,
//方法声明
METHOD,
//参数声明
PARAMETER,
//构造器声明
CONSTRUCTOR,
//局部变量声明
LOCAL_VARIABLE,
//注解类型声明
ANNOTATION_TYPE,
//包声明
PACKAGE,
//类型参数声明(Java1.8开始使用)
TYPE_PARAMETER,
//类型使用(Java1.8开始使用)
TYPE_USE
}
- 2.@Retention 表示需要在什么级别保存该注解信息。
RetentionPolicy参数包括
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*注解将被编译器丢弃
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*注解被编译器保存在类文件中。但在运行的时候没有被VM保存
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
* 注解将被编译器保存在类文件中,在运行的时候也会被VM保存。因此可通过反射机制读取注解的信息
*/
RUNTIME
}
3.@Documented 将此注解包含在Javadoc中
4.@Inherited 允许子类继承父类中的注解
定义注解的语法
package com;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by JohnTsai on 15/11/7.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
注解的定义很像一个空的接口。定义注解时,会需要一些元注解(meta-annotation,如上所示)
在注解中,一般都会包含一些元素以表示某些值。分析处理注解时,程序或工具可以利用这些值。
注解的元素看起来就像接口的方法,唯一的区别是可以为它设置默认值。
package com;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by JohnTsai on 15/11/7.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
public int id();
//default设置默认值
public String description() default "no description";
}
使用注解的语法
package com;
/**
* Created by JohnTsai on 15/11/7.
*/
public class Testable {
public void execute(){
System.out.println("Executing...");
}
@Test void testExcute(){
execute();
}
}
注解的元素在使用时表现为名-值对的形式。
package com;
/**
* Created by JohnTsai on 15/11/7.
*/
public class PasswordUtils {
@UseCase(id = 47, description = "Passwords must cantain at least one numeric!")
public boolean validatePassword(String password) {
return (password.matches("\\w*\\d\\w*"));
}
@UseCase(id = 48)
public String encryptPassword(String password) {
return new StringBuilder(password).reverse().toString();
}
}
4.什么时候使用注解
每当创建描述符性质的类或接口时,如果包含了重复性的工作,就可以考虑使用注解来简化与自动化该过程。
5.编写注解处理器
使用注解很重要的一部分就是创建与使用注解处理器。Java SE5拓展了反射机制的API(构造这类工具),还提供了外部工具apt帮助我们解析带有注解的Java源代码。
package com;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Created by JohnTsai on 15/11/8.
*/
public class UseCaseTracker {
public static void trackUseCases(List<Integer> useCases,Class<?> clz){
for(Method m :clz.getDeclaredMethods()){
UseCase useCase = m.getAnnotation(UseCase.class);
if(useCase!=null){
System.out.println(useCase.id()+useCase.description());
useCases.remove(new Integer(useCase.id()));
}
}
for(int i:useCases){
System.out.println("Warning:Missing use case -"+i);
}
}
public static void main(String[] args) {
List<Integer> useCases = new ArrayList<>();
Collections.addAll(useCases,47,48,49);
trackUseCases(useCases,PasswordUtils.class);
}
}
//output
/*
47Passwords must cantain at least one numeric!
48no description
Warning:Missing use case -49
*/
使用了两个反射的方法:getDeclaredMethods()和getAnnotation()(这两个方法都属于AnnotatedElement接口,Class,Method和Field等类都实现了这个接口)
注解元素
注解元素可用的类型如下:
1.所有的基本类型(如int,float,boolean等等)
2.String
3.Class
4.enum
5.Annotation
6.以上类型的数组
默认值限制
编译器对元素的默认值有限制。
不能有不确定的值
(即要么具有默认值,要么使用注解时提供的元素的值)
我们可以查看AndroidAnnotations中的@ViewById的源码,查看它的写法,就能看出默认值的写法:
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface ViewById {
int value() default ResId.DEFAULT_VALUE;
String resName() default "";
}
Java编程思想学习笔记——注解的更多相关文章
- [Java编程思想-学习笔记]第3章 操作符
3.1 更简单的打印语句 学习编程语言的通许遇到的第一个程序无非打印"Hello, world"了,然而在Java中要写成 System.out.println("He ...
- Java编程思想 学习笔记1
一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...
- [Java编程思想-学习笔记]第1章 对象导论
1.1 抽象过程 Java是一门面向对象的语言,它的一个优点在于只针对待解问题抽象,而不用为具体的计算机结构而烦心,这使得Java有完美的移植性,也即Java的口号"Write Once, ...
- Java编程思想 学习笔记11
十一.持有对象 通常,程序总是根据运行时才知道的某些条件去创建新对象.在此之前,不会知道所需对象的数量,甚至不知道确切的类型. Java实用库还提供了一套相当完整的容器类来解决这个问题,其中基本的类 ...
- Java编程思想 学习笔记7
七.复用类 1.组合语法 在新的类中产生现有类的对象.由于新的类是由现有类的对象所组成,所以这种方法叫做组合. 类中域为基本类型时能够自动被初始化为零.对象引用被初始化为null. 编译器不是简单地为 ...
- Java编程思想学习笔记——类型信息
前言 运行时类型信息(RTTI:Runtime Type Information)使得我们可以在程序运行时发现和使用类型信息. Java在运行时识别对象和类的信息的方式: (1)一种是RTTI,它假定 ...
- Java编程思想 学习笔记12
十二.通过异常处理错误 Java的基本理念是“结构不佳的代码不能运行”. Java中的异常处理的目的在于通过使用少于目前数量的代码来简化大型.可靠的程序的生成,并且通过这种方式可以使你更加自信:你的 ...
- Java编程思想 学习笔记10
十.内部类 可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性.然而必须要了解,内部类和组合是 ...
- Java编程思想 学习笔记5
五.初始化与清理 1.用构造器确保初始化 在Java中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.创建对象时,如果其类具有构造器,Java就会在用户有能力操作对象之前自动调用相应的构造 ...
随机推荐
- css3 data-attribute属性打造漂亮的按钮
之前介绍了几款css3实现的按钮,今天为网友来款比较新鲜的,用css3的data-attribute属性开发按钮,当鼠标经过显示按钮的详细信息.而且实现过程很简单,几行代码就搞定.大家试一试吧.如下图 ...
- with open
再考虑一个场景,要读取文件内容,并把年龄和名字的顺序交换存成新文件age_name.txt,这时可以同时打开两个文件:with open('name_age.txt', 'r') as fread, ...
- 【Linux/CentOS】Boolean ftp_home_dir is not defined
安装完vsftpd软件后,因为CentOS系统的SELinux安全策略默认是没有开启FTP服务,直接访问会报错500 OOPS,所以需要修改为允许使用FTP服务. 目标:希望ftp用户可以访问自己的家 ...
- Spring高级装配(二) 条件化的bean
如果你希望一个bean在特定的条件下才会出现: 应用的类路径下包含特定的库时才创建 只有当某个特定的bean也声明之后才会创建 某个特定的环境变量设定之后才创建某个bean 在Spring 4之前,很 ...
- oozie 重新提交作业
在oozie的运行过程当中可能会出现错误,比如数据库连接不上,或者作业执行报错导致流程进入suspend或者killed状态,这个时候我们就要分析了,如果确实是数据或者是网络有问题,我们比如把问题解决 ...
- iis 配置多域名,多https
当一个https的请求到达IIS服务器时,https请求为加密状态,需要拿到相应的服务器证书解密请求.由于每个站点对应的证书不同,服务器需要通过请求中不同的主机头来判断需要用哪个证书解密,然而主机头作 ...
- VB6学习笔记
1.数据库读取 [工程]菜单的[引用]菜单项,打开引用对话框,选中[Microsoft ActiveX Data Objects 6.1 Library] [工程]菜单的[引用]菜单项,打开引用对话框 ...
- Spring Cloud Config 服务端与 客户端之间的关系
1.服务端有两个可配置项 # 是否在服务器端进行解密操作,默认开启. # 如果改为不在服务器端开启(false) # 那么一定要将encrypt.key 删除. # 否则会出现客户端无法解密. # 为 ...
- 深入浅出学习Hibernate框架(二):JDBC基础操作
上篇博客<深入浅出学习Hibernate框架(一):从实例入手初识Hibernate框架>简单介绍了一下Hibernate框架,并且举了一个实例来了解Hibernate.这篇博客将介绍JD ...
- 《jdk10》删除javah.exe文件,在Android studio编译jni,使用jdk10生成头文件
今天在用“死丢丢”编译so包的时候,只要一输入"javah -jni..."的命令就会一直提示 'javah'不是内部命令或外部命令,也不是可运行的程序或批处理文件 找了很久才发现 ...