Java中的注解

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 numeric
Found Use Case:48 no description
Found Use Case:49 New passwords can't equal previously used ones
Warning: 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编程思想》第四版,仅作为学习和总结。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值