注解的学习以及使用
说明
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据.
内置的注解
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在代码的注解是
@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。
作用在其他注解的注解(元注解)是:
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
从 Java 7 开始,额外添加了 3 个注解:
@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
@Retention | 表示需要在什么级别保存保存该注解信息 |
---|---|
SOURCE | 注解将被编译器丢丢弃 |
CLASS | 注解在class文件中可用,但会被VM丢弃 |
RUNTIME | VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息 |
@Documented | 将此注解包含在javadoc中 |
---|
@Target | 表示该注解可以用于什么地。ElementType参数包括 |
---|---|
CONSTRUCTOR | 构造器的说明 |
FIFLD | 域说明 |
LOCAL_VARIABLE | 局部变量说明 |
METHOD | 方法说明 |
PACKAGE | 包声明 |
PARAMETER | 参数说明 |
TYPE | 类,接口(包括注解类型)或enum声明 |
@Inherited | 允许子类继承父类的注解 |
---|
OK,说完基本的注解使用,我们可以做个小demo,加深对注解的理解。
Demo内容:
创建一个Bean类引用自己创建的注解,然后使用jdbc读取注解的sql,在进行创建
Demo做法如下,将创建下列注解:
@DBTable – 生成一个数据库表
@Constraints --此注解包含主键,是否为空,唯一索引
@SQLString --定义SQL类型
@SQLInteger --定义SQL类型
接下来,定义一个简单的bean类,实现以上注解
Member
最后,实现注解处理器类以及jdbc工具类
TableCreator – 注解处理类
DBUtil – jdbc工具类
代码如下:
@DBTable
package com.qing.annotations.database;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: Learn_Qing
* @description 此注解是为告诉注解处理器,需要为此注解生成一个数据库表:
* @author: Marven
* @date: 2020-03-21 21:20
**/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
public String name() default "";
}
@Constraints
package com.qing.annotations.database;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: Learn_Qing
* @description 修饰JavaBean域做准备:
* @author: Marven
* @date: 2020-03-21 21:25
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
boolean primaryKey() default false;
boolean allowNull() default true;
boolean unique() default false;
}
@SQLString
package com.qing.annotations.database;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: Learn_Qing
* @description:
* @author: Marven
* @date: 2020-03-21 21:28
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
int value() default 0;
String name() default "";
Constraints constraints() default @Constraints;
}
@SQLInteger
package com.qing.annotations.database;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: Learn_Qing
* @description:
* @author: Marven
* @date: 2020-03-21 21:31
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
String name() default "";
Constraints constraints() default @Constraints;
}
Member
package com.qing.annotations.database;
/**
* @program: Learn_Qing
* @description 注意,此域中每个注解都内嵌了@Constraints注解:
* @author: Marven
* @date: 2020-03-21 21:37
**/
@DBTable(name = "MEMBER")//数据库将会创建名称为"MEMBER"表
public class Member {
@SQLString(30) //数据库会将表的长度的设成30
String firstName;
@SQLString(50)
String lastName;
@SQLInteger
Integer age;
@SQLString(value = 30,constraints = @Constraints(primaryKey = true))//将handle列指定为主键
String handle;
static int memberCount;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Integer getAge() {
return age;
}
public String getHandle() {
return handle;
}
public static int getMemberCount() {
return memberCount;
}
}
DBUtil
package com.qing.annotations.database.util;
import java.sql.*;
/**
* @program: Learn_Qing
* @description:
* @author: Marven
* @date: 2020-03-22 12:16
**/
public class DBUtil
{
/**
* 注意,加载此驱动需要用到mavenJar包为
* <dependency>
* <groupId>mysql</groupId>
* <artifactId>mysql-connector-java</artifactId>
* <version>8.0.15</version>
* </dependency>
*/
private static String driver = "com.mysql.cj.jdbc.Driver"; //用于加载驱动
private static String url = "jdbc:mysql://192.168.213.136/mall?characterEncoding=utf-8"; //数据库地址
private static String username = "root"; //用户名
private static String password = "root"; //密码
//连接数据库
public static Connection open()
{
try
{
Class.forName(driver); //加载驱动
return DriverManager.getConnection(url, username, password);
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}
//关闭数据库
public static void close(Connection conn)
{
if(conn!=null)
{
try
{
conn.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
TableCreator
package com.qing.annotations.database;
import com.qing.annotations.database.util.DBUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* @program: Learn_Qing
* @description:
* @author: Marven
* @date: 2020-03-21 22:52
**/
public class TableCreator {
public static void main(String[] args) throws ClassNotFoundException {
String sql = "";
if(args.length < 1){
System.out.println("参数: 带注解的类");
System.exit(0);
}
for (String className : args){
Class<?> cl = Class.forName(className);
DBTable dbTable = cl.getAnnotation(DBTable.class);//getAnnotation方法返回该元素的指定类型的注解,如果是这样的注解,否则返回null。
if(dbTable == null){
System.out.println("没有 DATable 这个注解类 " + className);
continue;
}
String tableName = dbTable.name();
// 如果名称为空,请使用类名称
if(tableName.length()<1)
tableName = cl.getName().toUpperCase();
List<String> columnDefs = new ArrayList<String>();
//getDeclaredFields()获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
for (Field field : cl.getDeclaredFields()){
String columnName = 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)
columnName = field.getName().toUpperCase();
else
columnName = sINT.name();
columnDefs.add(columnName + " INT " + getConstraints(sINT.constraints()));
}
if(anns[0] instanceof SQLString){
SQLString sString = (SQLString) anns[0];
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) + ");";
System.out.println("sql创建表 " + className + " 是 :\n" + tableCreate);
sql = tableCreate;
}
//使用jdbc创建数据库表
Connection conn = DBUtil.open(); //连接数据库
try
{
Statement stmt = conn.createStatement(); //静态操作sql语句
stmt.execute(sql);
System.out.println("创建表成功");
} catch (SQLException e)
{
e.printStackTrace();
}
finally
{
DBUtil.close(conn);
}
}
}
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;
}
}
温馨提示:
运行TableCreator类需要做一下设置:
直接图片说明,简单明了
接下来需要将Member类写到Program arguments中:
ok,点击右下角OK,在点击运行
下一步,我们可以到数据库中查询这张表是否存在
SQL: SHOW COLUMNS FROM MEMBER;
结果如下:
总结:
通过上面的展示的一个小Demo,可以使大家有所了解,老子有言:“上士闻道,勤而行之”,希望大家都能举一反三,如果能在实践中激发灵感,那是最好不过!
下一篇: Apriori算法的Python实现
推荐阅读
-
在新版Unity中使用Protobuf以及使用Google.Protobuf.WellKnownTypes中的Duration Timestamp
-
Java8语法中获取程序耗时以及Period,Duration,ChronoUnit类的使用
-
Struts中的reset按钮以及使用js捕获html标签
-
使用php完成一个用户注册以及管理的demo(二)
-
浅谈layer的Icon样式以及一些常用的layer窗口使用方法
-
上拉电阻和下拉电阻的作用以及使用场合
-
Android学习笔记之——使用Android的日志工具Log
-
新浪微博Oauth2.0授权 获取Access Token以及API的使用
-
Elasticsearch7 内置分词器的使用以及中文(IK)分词器的安装和使用
-
JDBC–MYSQLEclipse的连接以及简单的使用_MySQL