总结:第20章将注解,20.1与20.2介绍注解的基本语法,3种标准注解,4种用来创建自定义注解的元注解;
20.3与20.4介绍使用注解处理工具apt来处理注解(没看仔细);20.5介绍基于注解的单元测试(类似于Junit)
知识点:
-
定义在java.lang中的三种标准注解:@Override、@Deprecated、@SuppressWarnings
-
定义在java.lang.annotation中的四种元注解:
@Target 表示该注解可用在什么地方。可用的ElementType参数包括:
CONSTRUCTOR:构造器的声明
FIELD:域声明
LOCAL_VARIABLE: 局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明@Retention 表示需要在什么级别保存注解信息。可选的RetentionPolicy参数包括:
SOURCE:注解将被编译器丢弃;
CLASS:注解在class文件中可用,但会被JVM丢弃;
RUNTIME:JVM将在运行期也保留注解,因此可以通过反射机制读取注解的信息。@Documented 将此注解包含在Javadoc中 @Inherited 允许子类继承父类中的注解
-
使用@interface来定义注解:
123456789import
java.lang.annotation.*;
@Target
(ElementType.METHOD)
@Retention
(RetentionPolicy.RUNTIME)
@Documented
public
@interface
UseCase {
public
int
id();
public
String description()
default
"no description"
;
}
id与description是注解UseCase的元素,default用来定义元素的默认值。
-
编写注解处理器,主要依据反射实现。
AnnotatedElement接口(Class、Method、Field等类均实现了此接口)的getAnnotation(Class c)方法可以获取注解
-
注解元素的类型限制:
所有基本类型;String;Class;Enum;Annotation以及以上类型的数组。
-
注解元素的值:
要么具有默认值,要么使用注解是提供值;且非基本类型元素不能为null。
-
注解处理器示例:
-
定义注解:DBTable.java
1234567891011121314151617181920212223242526272829303132package
edu.zju.chwl.annotation;
import
java.lang.annotation.*;
@Target
(ElementType.TYPE)
@Retention
(RetentionPolicy.RUNTIME)
public
@interface
DBTable {
public
String name()
default
""
;
}
@Target
(ElementType.FIELD)
@Retention
(RetentionPolicy.RUNTIME)
@interface
Constraints{
boolean
primaryKey()
default
false
;
boolean
allowNull()
default
true
;
boolean
unique()
default
false
;
}
@Target
(ElementType.FIELD)
@Retention
(RetentionPolicy.RUNTIME)
@interface
SQLString{
int
value()
default
0
;
String name()
default
""
;
Constraints constraints()
default
@Constraints
;
}
@Target
(ElementType.FIELD)
@Retention
(RetentionPolicy.RUNTIME)
@interface
SQLInteger{
String name()
default
""
;
Constraints constraints()
default
@Constraints
;
}
- 使用注解:Student.java
123456789101112131415161718192021222324252627package
edu.zju.chwl.annotation;
@DBTable
(name=
"student"
)
public
class
Student {
@SQLInteger
(constraints=
@Constraints
(primaryKey=
true
,allowNull=
false
))
private
int
id;
@SQLString
(value=
30
)
private
String name;
@SQLInteger
private
int
age;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
public
int
getId() {
return
id;
}
}
-
注解处理器:CreateTable.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687package
edu.zju.chwl.annotation;
import
java.lang.annotation.Annotation;
import
java.lang.reflect.*;
import
java.util.*;
public
class
CreateTable {
public
static
void
main(String[] args){
String tableName;
List<String> columnList=
new
ArrayList<String>();
Class<Student> clazz=Student.
class
;
//获取表名
DBTable dbTable=clazz.getAnnotation(DBTable.
class
);
if
(
""
.equals(dbTable.name())){
tableName=clazz.getSimpleName().toLowerCase();
}
else
{
tableName=dbTable.name();
}
//获取所有列
Field[] fields=clazz.getDeclaredFields();
for
(Field field:fields){
StringBuilder sb=
new
StringBuilder();
Annotation[] ans=field.getAnnotations();
if
(ans.length<
1
){
continue
;
}
//可以理解为:SQLString继承自Annotation
if
(ans[
0
]
instanceof
SQLString){
SQLString sqlStr=(SQLString)ans[
0
];
if
(
""
.equals(sqlStr.name())){
sb.append(field.getName());
}
else
{
sb.append(sqlStr.name());
}
if
(sqlStr.value()==
0
){
sb.append(
" varchar(50)"
);
}
else
{
sb.append(
" varchar("
).append(sqlStr.value()).append(
")"
);
}
sb.append(getConstraint(sqlStr.constraints()));
}
if
(ans[
0
]
instanceof
SQLInteger){
SQLInteger sqlStr=(SQLInteger)ans[
0
];
if
(
""
.equals(sqlStr.name())){
sb.append(field.getName());
}
else
{
sb.append(sqlStr.name());
}
sb.append(
" int"
);
sb.append(getConstraint(sqlStr.constraints()));
}
columnList.add(sb.toString());
}
System.out.println(getCreateStr(tableName,columnList));
}
//根据表明,列信息创建SQL语句
private
static
String getCreateStr(String tableName, List<String> columnList) {
StringBuilder sbuf=
new
StringBuilder();
sbuf.append(
"CREATE TABLE "
).append(tableName).append(
"(\n"
);
for
(String column:columnList){
sbuf.append(
"\t"
).append(column).append(
",\n"
);
}
return
sbuf.substring(
0
,sbuf.length()-
2
)+
");"
;
}
//生成约束
private
static
String getConstraint(Constraints constraints) {
StringBuilder sbuf=
new
StringBuilder();
if
(!constraints.allowNull()){
sbuf.append(
" NOT NULL"
);
}
if
(constraints.primaryKey()){
sbuf.append(
" PRIMARY KEY"
);
}
if
(constraints.unique()){
sbuf.append(
" UNIQUE"
);
}
return
sbuf.toString();
}
}