相信大家或多或少接触或者使用过java的注解
比如java.lang包中的注解:
@Override :表示该方法覆盖父类的方法,当方法拼写错误或者和父类的对应不上时,编译器会报错
@SuppressWarnings :关闭编译器的警告报错
比如用过Spring框架的朋友肯定会熟悉很多注解。等等
基本用法
元注解:元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
1.@Target
2.@Retention,
3.@Documented,
4.@Inherited
这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。
@Target:
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention:
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
以上参考:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
自定义注解
注解的定义看起来和接口很像,只是在前面多了个@,并且在定义注解时,要用到我们上面介绍的元注解,来规定我们的注解使用的那个的地方。与java接口一样,注解会编译成class文件
下面是一个自定义注解,用来创建sql建表语句。
package zhujie;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义标签
* @author lk
*/
@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 SQLInteger{
String name() default "";
Constraints constraints() default @Constraints;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface SQLString{
int value() default 0;
String name() default "";
Constraints constraints() default @Constraints;
}
这样我们可以在类中使用我们的自定义注解
package zhujie;
@DBTable(name = "MEMBER")
public class Member {
@SQLString(30)
private String firstName;
@SQLString(50)
private String lastName;
@SQLInteger
private Integer age;
@SQLString(value = 30, constraints = @Constraints(primaryKey = true))
private String handle;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getHandle() {
return handle;
}
public void setHandle(String handle) {
this.handle = handle;
}
}
但是这样的注解和注释其实没有很大的区别,当注解和注解处理器一起使用时才能显示他的作用。
package zhujie;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class TableCreator {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(creator("zhujie.Member"));
}
private static String creator(String string) throws ClassNotFoundException {
Class<?> cl = Class.forName(string);
DBTable dbTable = cl.getAnnotation(DBTable.class);
if (dbTable == null) {
System.out.println("无效类名");
}
// 获取表名
String tableName = dbTable.name();
// 如果没有设置表名默认用类名大写
if (tableName.length() < 1) {
tableName = cl.getName().toUpperCase();
}
List<String> columnDefs = new ArrayList<>();
//遍历属性
for (Field field : cl.getDeclaredFields()) {
// 获取属性注解
Annotation[] anns = field.getAnnotations();
String columnName = null;
for (Annotation annotation : anns) {
if (annotation instanceof SQLString) {
SQLString sString = (SQLString) annotation;
if (sString.name().length() < 1) {
columnName = field.getName().toUpperCase();
} else {
columnName = sString.name();
}
columnDefs.add(
columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));
break;
} else if (annotation instanceof SQLInteger) {
SQLInteger sInt = (SQLInteger) annotation;
if (sInt.name().length() < 1) {
columnName = field.getName().toUpperCase();
} else {
columnName = sInt.name();
}
columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints()));
break;
} else {
continue;
}
}
}
//创建语句
StringBuilder createSql=new StringBuilder("CREATE TABLE "+tableName+"(");
for(String columnDef:columnDefs){
createSql.append("\r\n\t"+columnDef+",");
}
return createSql.substring(0,createSql.length()-1)+"\r\n);";
}
/*
* 属性后面的约束(唯一,主键,是否为空)
*/
private static String getConstraints(Constraints con) {
String constraints = "";
if (!con.allowNull()) {
constraints += " NOT NULL";
}
if (con.primaryKey()) {
constraints += " PRIMARY KEY";
}
if (con.unique()) {
constraints += " UNIQUE";
}
return constraints;
}
}
结果
CREATE TABLE MEMBER(
FIRSTNAME VARCHAR(30),
LASTNAME VARCHAR(50),
AGE INT,
HANDLE VARCHAR(30) PRIMARY KEY
);
通过上述的例子(来自java编程思想)我们大致可以了解到注解的作用和使用方法,当然这只是初步学习,我们用的例子对于真实的对象/关系映射而言(ORM数据库,比如hibernate),是很幼稚的。