在现实生活中,贴标签这种现象比比皆是。去超市,去商场,每个或者每类物品都会有它的标签,甚至在我们自己身上也会有标签,比如,程序猿、逗逼、单身狗、80/90后、屌丝……呵呵,太多了。有时候,我们也会戏谑朋友同事,给他们贴个标签逗逗乐。但是这篇的正题是注解,下面我会说说为什么我理解的注解就是贴标签,虽然有时候也会称它为“扣帽子”。

元注解

在java提供了四个元注解,元注解就是注解的注解。它们是:

1.@Target,

2.@Retention,

3.@Documented,

4.@Inherited

  在我们刚出生的时候,就已经被贴上标签了,我们的户籍按照地域划分,会被贴上河南河北、山东山西、湖南湖北等等23个省和四个直辖市中的其中一个。另外在我们的生命过程中也会经历标签的变换,小孩、未成年人、成年人、丈夫、妻子、父亲、母亲、爷爷奶奶等等。国家还会给我们贴上一个最普通的标签“公民”以及我们的继承的身份,农民或者城里人。为什么要说这些呢,因为JAVA中提供的四个元注解要表达的东西和提到的有共通之处。

@Target

  @Target说明了注解修饰的范围,就好像我们有地域划分,而Java中也会有包、接口、类、枚举、属性、方法、构造函数等。那么为了表示不同的区别,注解是这么写的:

1、包
@Target(ElementType.PACKAGE)
2、接口、类、枚举、注解
@Target(ElementType.TYPE)
3、注解
@Target(ElementType.ANNOTATION_TYPE)
4、构造函数
@Target(ElementType.CONSTRUCTOR)
5、局部变量
@Target(ElementType.LOCAL_VARIABLE)
6、方法
@Target(ElementType.METHOD)
7、方法的参数
@Target(ElementType.PARAMETER)

@Retention

  @Retention表示了注解的生命周期。我们在生命过程中会随着时间的变化而引起标签的变化,那么我们的标签本身也就说明了它有一定的生命周期,当我们未满18周岁的时候叫未成年人,在我们满18周岁的时候叫做成年人,等头发白了,走不动就被叫做老年人,而有的标签会伴随一生,例如男人或者女人。在JAVA中,注解也有它的生命周期,从源代码到编译后的Class文件,再到被JDK加载后的运行时就是整个周期。@Retention指定了它所要注解的注解的生命周期是什么,它会存在多长时间。JAVA中我们最常见的两个注解@SuppressWarnings和@Override,他们就只会存在于源代码中。下面是@Retention的取值:

1、在源代码中保留
@Retention( RetentionPolicy.SOURCE)
2、在Class文件中保留
@Retention( RetentionPolicy.CLASS)
3、在运行时保留
@Retention( RetentionPolicy.RUNTIME)

  @SuppressWarnings注解的源代码如下:

package java.lang;

import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

@Documented

  默认情况下javadoc是不包括注解信息的,但是当某一个注解被贴上@Documented标签的时候,那么当某个类或者方法的使用了被贴上@Documented这个标签的注解的时候,javadoc就会把注解信息也包含在生成的文档中。这个注解就不过度解读了,如果有兴趣的可以从网上自行查找相关资料。

@Inherited

  @Inherited注解主要说明了一种继承性,意思是子类可以继承父类中的该注解(注意:只有当被贴上@Inherited标签的注解被用在类上的时候子类才能获得这个注解)。就像之前提到的,如果父母是农村户口,那么他们的孩子也默认就是农村户口了。Spring中的@Qualifier注解,代码如下:

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier { String value() default ""; }

  @Qualifier注解可以被用在字段、方法、方法参数、类、接口、注解、枚举上,但是只有@Qualifier被用在类上的时候才能被它的子类继承,子类才可以获取到这个注解。

自定义注解

  除了一些我们生来就被贴上的标签意外,我们在日常生活中不管是主动的还是被动都会去主动的给别人贴一些标签以及被别人贴一些标签。当我们在公司,按照职能划分,会被贴上不同的岗位标签,便于安排工作;迟到,早退,全勤这些标签用于考勤;优秀员工,技术达人,管理精英等标签用来树立标杆,有助于提高积极性和向心力。那么这些标签被创造出来有没有用处呢,对于公司来说自然是有用处的。但是呢,逗逼这个标签对公司来说有没有用处呢,我想,除非公司愿意因为员工逗逼颁发逗逼奖这才有点用处,否则的话谁关心呢!贴个标签大多数时候并不会影响正常的生活,除了个人或者组织关注了你身上的标签的时候才会有影响,就像现在很多人一看到河南人三个字就开骂了一样……。其实这也是为了说明,注解并不会影响程序的正常运行,有或者没有并不影响什么,只有关注了这些注解的程序获得并且解析了注解进行处理以后才会更改程序本身的行为。

  我们知道JAVA的JDK中很多地方都用了注解,到我们使用Spring的时候,注解就被使用的更广泛了,Spring用注解来对bean进行分类,注册,注入以及管理,这些事情是Spring在扫描Bean的时候通过反射来获取Bean的注解信息,配合完成Bean的自动装配,进而进行管理,给我们提供了丰富多彩的功能。下面写一个利用反射来处理自定义注解的例子,这个例子就是简单生成一个建表语句,代码如下:

  1、创建@Table注解

package person.lb.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 表名
* @author nobounds
*
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value() default "";
}

   2、创建@Column注解:

package person.lb.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* 字段
* @author nobounds
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
String dataType() default "varchar(20)";
String comment() default "";
}

  3、创建实体类Users:

package person.lb.annotation;

@Table("users")
public class Users {
@Column(name="ID", dataType="int")
private int id; @Column(comment="用户名")
private String userName; @Column(name="pwd", comment="密码")
private String password; @Column(dataType="varchar(25)", comment="邮箱")
private String email; public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
}
}

  4、创建注解处理器AnnotationHandler:

package person.lb.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field; public class AnnotationHandler { public static void main(String[] args) {
StringBuilder sql = new StringBuilder("CREATE TABLE ");
try {
Class clazz = Class.forName("person.lb.annotation.Users");
//获取Users类上的Table注解
Table tableAnnotation = (Table) clazz.getAnnotation(Table.class);
//获取表名
String tableName = tableAnnotation.value().toUpperCase();
if("".equals(tableName)) {
tableName = clazz.getName().toUpperCase();
}
sql.append(tableName);
sql.append(" ( \n");
//获取类中的所有字段
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
//获取字段上的所有注解
Annotation[] fieldAnnotations = field.getAnnotations();
if(fieldAnnotations.length > 0) {
//遍历注解
for(Annotation fieldAnnotation : fieldAnnotations) {
//如果是@Field注解,那么进行处理
if(fieldAnnotation instanceof Column) {
//获取字段名
String columnName = ((Column) fieldAnnotation).name().toUpperCase();
if("".equals(columnName)) {
columnName = field.getName().toUpperCase();
}
//获取数据类型
String dataType = ((Column) fieldAnnotation).dataType().toUpperCase();
//获取注释
String comment = ((Column) fieldAnnotation).comment();
if("".equals(comment)) {
sql.append(columnName + "\t" + dataType + ",\n");
} else {
sql.append(columnName + "\t" + dataType + " COMMENT '" + comment + "',\n");
}
}
}
}
}
sql.append(" ) ");
System.out.println("生成的sql语句为:\n" + sql.toString()); } catch (ClassNotFoundException e) {
e.printStackTrace();
} } }

执行结果如下:

生成的sql语句为:
CREATE TABLE USERS (
ID INT,
USERNAME VARCHAR(20) COMMENT '用户名',
PWD VARCHAR(20) COMMENT '密码',
EMAIL VARCHAR(25) COMMENT '邮箱',
)

上面是一个简单的生成sql的例子,例子中忽略了某些非空判断,逻辑并不严谨,仅作为参考使用。如果大家觉得有问题请留言!

我对java的理解(一)——注解就是贴标签的更多相关文章

  1. Java学习记录-注解

    注解 一.org.springframework.web.bind.annotation ControllerAdviceCookieValue : 可以把Request header中关于cooki ...

  2. Effective Java通俗理解(持续更新)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  3. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  4. JAVA提高五:注解Annotation

    今天我们学习JDK5.0中一个非常重要的特性,叫做注解.是现在非常流行的一种方式,可以说因为配置XML 比较麻烦或者比容易查找出错误,现在越来越多的框架开始支持注解方式,比如注明的Spring 框架, ...

  5. Effective Java通俗理解(上)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  6. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  7. Java深度理解——Java字节代码的操纵

    导读:Java作为业界应用最为广泛的语言之一,深得众多软件厂商和开发者的推崇,更是被包括Oracle在内的众多JCP成员积极地推动发展.但是对于 Java语言的深度理解和运用,毕竟是很少会有人涉及的话 ...

  8. Java枚举类与注解详解——一篇文章读懂枚举类与注解详

    目录 一.枚举类 ① 自定义枚举类 ② enum关键字定义枚举类 ③ enum 枚举类的方法 ④ enum 枚举类实现接口 二.注解 ① 生成文档相关注解 ②注解在编译时进行格式检查 ③注解跟踪代码的 ...

  9. 深入理解Spring注解机制(一):注解的搜索与处理机制

    前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...

随机推荐

  1. KeyboardJS 开发指南 - 与 Three.js 配合使用的捕捉键盘组合键库

    KeyboardJS 开发指南 - 与 Three.js 配合使用的捕捉键盘组合键库 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非 ...

  2. wireshark:Couldn't run /usr/bin/dumpcap in child process: Permission denied

    When start wireshark, I met an error like: 引用 Couldn't run /usr/bin/dumpcap in child process: Permis ...

  3. Unity Texture2D的sRGB(Color Texture)的作用

    在gramma空间下,勾选与否无关. 在liner空间下,勾选shader会自动将读到的像素作gramma矫正,即x的0.45次方 不勾选,shader读到的就是原始的颜色值 然后unity如果选了g ...

  4. Unity 游戏对象消失 enable,destroy与active的区别

    gameObject.SetActive(false):是否在场景中停用该物体,停用后Hierarchy窗口呈灰色,用Find函数也找不到.如果该物体有子物体,要用SetActive Recursir ...

  5. Mysql主从复制,实现数据同步

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...

  6. Lumen开发:如何向 IoC 容器中添加自己定义的类

    版权声明:本文为博主原创文章,未经博主允许不得转载. 先在起始文件bootstrap/app.php加上$app->register(App\Providers\User\UserService ...

  7. mysql导出数据或结构

    导出整个数据库结构和数据 $ mysqldump -h localhost -uroot -p123456 database > dump.sql 导出单个数据表结构和数据 $ mysqldum ...

  8. cocos2dx的ui封装

    cocos2dx里加载cocosudio导出的ui配置文件,在这之上封装了一下,封装核心类包括 UIManager,UILayer,UIOwner UIManager是所有ui总的管理类,代码如下: ...

  9. python三大器

    装饰器 装饰器的作用: 装饰器的本质:一个闭包函数 (高阶函数+嵌套函数) 装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展 闭包原理 装饰器执行流程 带多个参数函数 import ...

  10. Python 面试题(上)

    Python语言特性 1 Python的函数参数传递 看两个例子: a = 1 deffun(a): a = 2 fun(a) printa # 1 a = [] deffun(a): a.appen ...