Java中的注解

来源:互联网 发布:深圳航天信息开票软件 编辑:程序博客网 时间:2024/05/21 11:14

1、什么是注解?

注解(也被称为 元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。

2、标准注解与元注解

Java内置了三种标准注解和四种元注解

3种标准注解(定义在java.lang中):

@Override  表示当前的方法定义将覆盖超类中的方法。如果你不小心拼写错误,或者方法签名对不上覆盖的方法,编译器就会发出错误提示。

@Deprecated  如果程序员使用了注解为它的元素,那么编译器会发出警告信息。

@SuppressWarning 关闭当前的编译器警告信息。

4种元注解(元注解专职负责注解其他的注解)

@Target  表示该注解可以用于什么地方。可能的ElementType参数包括:

CONSTRUCTOR:构造器的声明

FIELD:域声明(包括enum实例)

LOCAL_VARIABLE:局部变量声明

METHOD:方法声明

PACKAGE:包声明

PARAMETER:参数声明

TYPE:类、接口(包括注解类型)或enum声明

@Retention 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:

SOURCE:注解将被编译器丢弃

CLASS:注解在class文件中可用,但会被VM丢弃

RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息

@Document 将此注解包含在Javadoc中

@Inherited 允许子类继承父类中的注解

3、自定义一个注解

自定义一个简单的注解(没有元素的注解称为标记注解)

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Test {}
自定义一个包含元素的注解

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface UseCase {public int id();public String description() default "no description";}

4、使用自定义注解

import java.util.List;import com.zhangmingji.annotation.UseCase;public class PasswordUtils {@UseCase(id=47, description="password must contain 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();}@UseCase(id=49, description="New passwords can't equal previously used ones")public boolean checkForNewPassword(List<String> prePasswords, String password){return !prePasswords.contains(password);}}
5、编写注解处理器

import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Collections;import java.util.List;import com.zhangmingji.annotation.UseCase;import com.zhangmingji.use.PasswordUtils;public class UseCaseTracker {public static void trackUseCases(List<Integer> useCases, Class<?> cl){for(Method m : cl.getDeclaredMethods()){UseCase uc = m.getAnnotation(UseCase.class);if(uc != null){System.out.println("Found Use Case:" + uc.id() + " " + uc.description());useCases.remove(new Integer(uc.id()));}}for(int i : useCases){System.out.println("Warning: Missing use case-" + i);}}public static void main(String[] args) {List<Integer> useCases = new ArrayList<Integer>();Collections.addAll(useCases, 47, 48, 49, 50);trackUseCases(useCases, PasswordUtils.class);}}

运行结果:

Found Use Case:47 password must contain at least one numericFound Use Case:48 no descriptionFound Use Case:49 New passwords can't equal previously used onesWarning: Missing use case-50
6、注解元素

在前面我们已经定义了一个包含元素id、description的注解,

注解元素可用的类型如下:

所有基本类型(int,float,boolean

String

Class

enum

Annotation

以上类型的数组

如果你使用了其他类型,那么编译器就会报错;也不允许使用任何包装类型;注解也可以作为基本元素类型,也就是说注解可以嵌套

7、默认值限制
(1)、元素不能有不确定的值。也就是说,元素必须要么具有默认值,要么使用注解时提供元素的值。

(2)、对于非基本类型的元素,无论在源代码中声明时,或是在注解接口中定义默认值时,都不能以null作为其值。

(3)、注解不支持继承。

8、通过注解生成建表语句

package com.zhangmingji.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)//类、接口、或者ENUM声明@Retention(RetentionPolicy.RUNTIME)public @interface DBTable {public String name() default "";}

package com.zhangmingji.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Constraints {boolean primaryKey() default false;boolean allowNull() default true;boolean unique() default false;}

package com.zhangmingji.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface SQLString {int value() default 0;String name() default "";Constraints constraints() default @Constraints;}

package com.zhangmingji.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface SQLInteger {String name() default "";Constraints constraints() default @Constraints;}

使用以上自定义的注解

package com.zhangmingji.use;import com.zhangmingji.annotation.Constraints;import com.zhangmingji.annotation.DBTable;import com.zhangmingji.annotation.SQLInteger;import com.zhangmingji.annotation.SQLString;@DBTable(name="MEMBER")public class Member {@SQLString(30) String firstName;@SQLString(50) String lastName;@SQLInteger Integer age;@SQLString(value=30, constraints=@Constraints(primaryKey=true))String handle;static int memberCount;public String getHandle(){return this.handle;}public String getFirstName(){return this.firstName;}public String getLastName(){return this.lastName;}public String toString(){return handle;}public Integer getAge(){return age;}}

实现处理器

package com.zhangmingji.process;import java.lang.annotation.Annotation;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import com.zhangmingji.annotation.Constraints;import com.zhangmingji.annotation.DBTable;import com.zhangmingji.annotation.SQLInteger;import com.zhangmingji.annotation.SQLString;public class TableCreator {public static void main(String[] args) throws Exception {if(args.length < 1){System.out.println("arguments: anotationed classes");System.exit(0);}for(String className : args){Class<?> cl = Class.forName(className);DBTable dbTable = cl.getAnnotation(DBTable.class);if(null == dbTable){System.out.println("no DBTable anotations in class " + className);continue;}String tableName = dbTable.name();//如果名字为空,则使用类名if(tableName.length() < 1){tableName =  cl.getName().toUpperCase();}List<String> columDefs = new ArrayList<String>();for(Field field : cl.getDeclaredFields()){String columName = null;Annotation[] anns = field.getDeclaredAnnotations();if(anns.length < 1){continue; //}if(anns[0] instanceof SQLInteger){SQLInteger sInt = (SQLInteger) anns[0];//如果没有指定名称,则使用属性名称if(sInt.name().length() < 1){columName = field.getName().toUpperCase();}else{columName = sInt.name();}columDefs.add(columName + " INT" + getConstraints(sInt.constraints()));}if(anns[0] instanceof SQLString){SQLString sString = (SQLString) anns[0];if(sString.name().length() < 1){columName = field.getName().toUpperCase();}else{columName = sString.name();}columDefs.add(columName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));}}StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "(");for(String columDef : columDefs){createCommand.append("\n " + columDef + "," );}String tableCreate = createCommand.substring(0, (createCommand.length() - 1)) + ");";System.out.println("Table create SQL for " + className + " is :\n" + tableCreate);}}/** * 构造约束 * @param con * @return */public static String getConstraints(Constraints con){String contraints = "";if(!con.allowNull()){contraints += " NOT NULL";}if(con.primaryKey()){contraints += " PRIMARY KEY";}if(con.unique()){contraints += " UNIQUE";}return contraints;}}

运行结果:

Table create SQL for com.zhangmingji.use.Member is :CREATE TABLE MEMBER( FIRSTNAME VARCHAR(30), LASTNAME VARCHAR(50), AGE INT, HANDLE VARCHAR(30) PRIMARY KEY);

以上内容来自《Java编程思想》第四版,仅作为学习和总结。












0 0
原创粉丝点击