注解

元注解:

  元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

    1.@Target      指定注解的作用范围

                     CONSTRUCTOR:用于描述构造器

            FIELD:用于描述域

            LOCAL_VARIABLE:用于描述局部变量

            METHOD:用于描述方法

            PACKAGE:用于描述包

            PARAMETER:用于描述参数 

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

                    TYPE_PARAMETER :TYPE_PARAMETER 标注在类型参数上 class D<@Parameter T> { }

                    TYPE_USE :除了class外任何类型都可以注释

//TYPE_USE则可以用于标注任意类型(不包括class)//用于父类或者接口class Image implements @Rectangular Shape { }

 

//用于构造函数new @Path String("/usr/bin")

 

//用于强制转换和instanceof检查,注意这些注解中用于外部工具,它们不会对类型转换或者instanceof的检查行为带来任何影响。String path=(@Path String)input;if(input instanceof @Path String)

 

//用于指定异常public Person read() throws @Localized IOException.

 

//用于通配符绑定List<@ReadOnly ? extends Person>List<? extends @ReadOnly Person>

    2.@Retention    定义注解保留的时间长短

                     取值(RetentionPoicy)有:

 

            SOURCE:在源文件中有效(即源文件保留)

                     CLASS:在class文件中有效(即class保留)

                     RUNTIME:在运行时有效(即运行时保留)

    3.@Documented 

                     @Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

    4.@Inherited

        Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

  注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

 当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

             5.@Repeatable

          它表示在同一个位置重复相同的注解。在没有该注解前,一般是无法在同一个类型上使用相同的注解的

自定义注解

定义注解格式:

  public @interface 注解名 {定义体}

  注解参数的可支持数据类型:

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)

2.String类型

3.Class类型

4.enum类型

5.Annotation类型

6.以上所有类型的数组

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface AnnotationElementDemo {

//声明枚举

public enum Color{Red,Green};



//枚举类型

public Color color() default Color.Red;



//String 类型

public String value() default "";



//基本类型

public boolean show() default false;



//class类型

Class<?> classT() default Void.class;



//数组类型

int[] ids() default {};



//注解类型

Reference reference() default @Reference("test");



}

public enum ElementType {

/**标明该注解可以用于类、接口(包括注解类型)或enum声明*/

TYPE,



/** 标明该注解可以用于字段(域)声明,包括enum实例 */

FIELD,



/** 标明该注解可以用于方法声明 */

METHOD,



/** 标明该注解可以用于参数声明 */

PARAMETER,



/** 标明注解可以用于构造函数声明 */

CONSTRUCTOR,



/** 标明注解可以用于局部变量声明 */

LOCAL_VARIABLE,



/** 标明注解可以用于注解声明(应用于另一个注解上)*/

ANNOTATION_TYPE,



/** 标明注解可以用于包声明 */

PACKAGE,



/**

* 标明注解可以用于类型参数声明(1.8新加入)

* @since 1.8

*/

TYPE_PARAMETER,



/**

* 类型使用声明(1.8新加入)

* @since 1.8

*/

TYPE_USE

}

 

注解不支持继承

注解是不支持继承的,因此不能使用关键字extends来继承某个@interface,但注解在编译后,编译器会自动继承java.lang.annotation.Annotation接口,这里我们反编译前面定义的DBTable注解

package com.zejian.annotationdemo;



import java.lang.annotation.Annotation;//反编译后的代码

public interface DBTable extends Annotation{

public abstract String name();

}

虽然反编译后发现DBTable注解继承了Annotation接口,请记住,即使Java的接口可以实现多继承,但定义注解时依然无法使用extends关键字继承@interface。

注解实现数据建表

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;



@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface DBTable {

//数据库的表名

String name() default "";

}



@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface SQLInteger {



//对应数据库的列名

String name() default "";



Constraints constraints() default @Constraints;

}



@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface SQLString {



//对应数据库的列名

String name() default "";

//对应列的长度

int value() default 0;

//约束

Constraints constraints() default @Constraints;

}



@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface Constraints {



//判断是否作为主键约束

boolean primaryKey() default false;

//判断是否允许为null

boolean allowNull() default false;

//判断是否唯一

boolean unique() default false;

}



@DBTable(name = "Member")

public class Member {



@SQLInteger(name = "id",constraints = @Constraints(primaryKey = true,allowNull = false,unique = true))

private String id;



@SQLString(name = "name",value = 125)

private String name;



@SQLString(name = "age",constraints = @Constraints(allowNull = true))

private int age;



@SQLString(name = "description",value = 256, constraints = @Constraints(allowNull = true))

private String description;

}





public class TableCreator {



public static String createTableSql(String className) throws ClassNotFoundException {

Class<?> cl = Class.forName(className);

DBTable dbTable = cl.getAnnotation(DBTable.class);

//如果没有表注解,直接返回

if(dbTable == null) {

System.out.println(

"No DBTable annotations in class " + className);

return null;

}



String tableName = dbTable.name();

// If the name is empty, use the Class name:

if(tableName.length() < 1)

tableName = cl.getName().toUpperCase();



List<String> columnDefs = new ArrayList<String>();

//通过Class类API获取到所有成员字段

for(Field field : cl.getDeclaredFields()) {

String columnName = null;

//获取字段上的注解

Annotation[] anns = field.getDeclaredAnnotations();

if(anns.length < 1)

continue; // Not a db table column



//判断注解类型

if(anns[0] instanceof SQLInteger) {

SQLInteger sInt = (SQLInteger) anns[0];

//获取字段对应列名称,如果没有就是使用字段名称替代

if(sInt.name().length() < 1)

columnName = field.getName().toUpperCase();

else

columnName = sInt.name();

//构建语句

columnDefs.add(columnName + " INT" +

getConstraints(sInt.constraints()));

}

//判断String类型

if(anns[0] instanceof SQLString) {

SQLString sString = (SQLString) anns[0];

// Use field name if name not specified.

if(sString.name().length() < 1)

columnName = field.getName().toUpperCase();

else

columnName = sString.name();

columnDefs.add(columnName + " VARCHAR(" +

sString.value() + ")" +

getConstraints(sString.constraints()));

}





}

//数据库表构建语句

StringBuilder createCommand = new StringBuilder(

"CREATE TABLE " + tableName + "(");

for(String columnDef : columnDefs)

createCommand.append("\n " + columnDef + ",");



// Remove trailing comma

String tableCreate = createCommand.substring(

0, createCommand.length() - 1) + ");";

return tableCreate;

}





/**

* 判断该字段是否有其他约束

* @param con

* @return

*/

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;

}



public static void main(String[] args) throws Exception {

String[] arg={"com.annotationtest.DBAnnotation.Member"};

for(String className : arg) {

System.out.println("Table Creation SQL for " +

className + " is :\n" + createTableSql(className));

}



/**

* 输出结果:

Table Creation SQL for com.annotationtest.DBAnnotation.Member is :

CREATE TABLE Member(

    id INT NOT NULL PRIMARY KEY UNIQUE,

    name VARCHAR(125) NOT NULL,

    age VARCHAR(0),

    description VARCHAR(256));

*/

}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值