java基础之注解

删除回忆录丶 提交于 2020-08-09 21:23:38

点击上方“程序猿小哈”,选择“置顶公众号”

有趣有内涵的文章第一时间送达!

注解的定义

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

注解基本概念

基本注解

java SE5内置了三种,定义在java.lang中的注解提供使用

  • @Override 表示当前的方法定义将覆盖超类中的方法.

  • @Deprecated 标识为启用,在使用这个元素时会有警告提示

  • @SuppressWarnings 关闭不当的编译器警告信息

另外提供了四种注解(元注解),用于创建注解.

  • @Target 用来定义你的注解将应用在什么地方
    可选的ElementType类型
    CONSTRUCTOR:构造器的声明
    FIELD:域账号(包括enum实例)
    LOCAL_VARLABLE:局部变量声明
    METHOD:方法声明
    PACKAGE:包声明
    PARAMETER:参数声明
    TYPE:类、接口(包括注解类型)或enum声明
    
  • @Retention 表示需要在什么级别保存该注解信息
    可选的RetentionPolicy类型
    SOURCE:源代码
    CLASS:类文件
    RUNTIME:运行时
    
  • @Documented 将此注解包含在javadoc中

  • @Inherited 运行子类继承父类中的注解

注解元素

注解可以添加的元素:

  • 所有基本类型(int float double boolean等)

  • String

  • Class

  • enum

  • Annotation

  • 以上的数组类型

没有元素的注解称为标记注解(marker annotation) 例如@Override

使用注意事项

  1. 默认值限制 编译器对元素的默认值很挑剔,元素不能有不确定的值(元素必须有默认值,或者使用时设置).默认值不能为null,可以使用""或者负数来自己标识某个元素不存在.

  2. 注解不可继承.可以使用注解上加注解,或者元素上使用注解来实现这个功能

注解的使用案例 -- 使用注解实现自动生成创建表sql功能

自定义注解

使用元注解来创建自定义注解使用,是最基础的功能,按照上文的定义创建注解.

创建一个对应数据库DB的注解 @DBTable

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {

    public String name() default ""; //表名

}

创建一个带注解元素的注解 @SQLInteger

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {

    String name() default "";

    Constraints constraints() default @Constraints;

}

创建约束条件注解 @Constraints

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {

    /**
     * 主键
     */
    public boolean primaryKey() default false;

    /**
     * 是否可以为空
     * @return
     */
    public boolean allowNull() default  true;

    /**
     * 是否唯一
     * @return
     */
    public boolean unique() default false;
}

使用注解

前面我们已经创建了注解,那么就需要使用起来.

创建一个和数据库对应用的entity类  Member

@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 handel;

    static int memberCount;


    public String getHandel(){
        return handel;
    }

    public String getFirstName(){
        return firstName;
    }

    public String getLastName(){
        return lastName;
    }

    public String toString(){
        return handel;
    }

    public Integer getAge(){
        return age;
    }
}

注解处理器

在注解创建好以后,需要自己实现自己的注解处理器,来对注解进行处理.如果没有注解处理器的话,注解的功能就等同于注释了.

现在写一个实现读取注解生成sql的注解处理器TableCreator

public class TableCreator {
    public static void main(String[] args) throws ClassNotFoundException {
        String[] args2 = {"db.Member"};
        if (args2.length<1){
            System.out.println("arguments: annotated classes");
            System.exit(0);
        }

        for (String className : args2) {
            Class<?> cl = Class.forName(className);
            //获取 dbTable注解类
            DBTable dbTable = cl.getAnnotation(DBTable.class);
            if (dbTable==null){
                System.out.println("No DB table in class"+className);
                continue;
            }
            String tableName = dbTable.name();
            //如果db.Member无表名 用类名
            if (tableName.length()<1){
                tableName = cl.getName().toUpperCase();
                System.out.println("cl.name:"+cl.getName());
                System.out.println("tableName:"+tableName);
            }

            List<String> columnDefs = new ArrayList<String>();
            //获取类的所有元素
            for (Field field : cl.getDeclaredFields()) {
                String columnName = null;
                //从元素中获取注解类型
                Annotation[] anns = field.getDeclaredAnnotations();
                if (anns.length<1){
                    continue;
                }
                //如果是SQLInteger类型 获取
                if (anns[0] instanceof SQLInteger){
                    SQLInteger sqlInteger = (SQLInteger) anns[0];
                    //如果无元素名称 使用类名
                    columnName = sqlInteger.name().length()<1?field.getName().toUpperCase():sqlInteger.name();
                    columnDefs.add(columnName+" INT"+getConstraints(sqlInteger.constraints()));
                }
                //其他类型 依次填写
                if (anns[0] instanceof SQLString){
                    SQLString sqlString = (SQLString) anns[0];
                    //如果无元素名称 使用类名
                    columnName = sqlString.name().length()<1?field.getName().toUpperCase():sqlString.name();
                    columnDefs.add(columnName+" VARCHAR("+sqlString.value()+")"+getConstraints(sqlString.constraints()));
                }
                //拼接创建sql
                StringBuilder createCommand = new StringBuilder(
                        "CREATE TABLE "+tableName+"("
                );
                for (String columnDef : columnDefs) {
                    createCommand.append("\n"+columnDef+",");
                }
                //去除最后的一个逗号
                String tableCreate = createCommand.substring(0,createCommand.length()-1);
                System.out.println("创建表的sql为: \n"+tableCreate);
            }
        }
    }

    public static String getConstraints(Constraints constraints){
        String constraintsStr = "";
        if (!constraints.allowNull()){
            constraintsStr+=" NOT NULL";
        }
        if (constraints.primaryKey()){
            constraintsStr+=" PRIMARY KEY";
        }
        if (constraints.unique()){
            constraintsStr+=" UNIQUE";
        }
        return constraintsStr;
    }
}

运行结果

创建表的sql为:
CREATE TABLE Member(
FIRSTNAME VARCHAR(30)
创建表的sql为:
CREATE TABLE Member(
FIRSTNAME VARCHAR(30),
LASTNAME VARCHAR(50)
创建表的sql为:
CREATE TABLE Member(
FIRSTNAME VARCHAR(30),
LASTNAME VARCHAR(50),
AGE INT
创建表的sql为:
CREATE TABLE Member(
FIRSTNAME VARCHAR(30),
LASTNAME VARCHAR(50),
AGE INT,
HANDEL VARCHAR(30) PRIMARY KEY

这样我们就实现了一个使用注解来自动生成数据库表创建sql的小功能.那么你学会注解的使用了吗.

喜欢本文的朋友们,欢迎长按下图关注订阅号程序猿小哈,收看更多精彩内容

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!