我对java的理解(一)——注解就是贴标签
在现实生活中,贴标签这种现象比比皆是。去超市,去商场,每个或者每类物品都会有它的标签,甚至在我们自己身上也会有标签,比如,程序猿、逗逼、单身狗、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的理解(一)——注解就是贴标签的更多相关文章
- Java学习记录-注解
注解 一.org.springframework.web.bind.annotation ControllerAdviceCookieValue : 可以把Request header中关于cooki ...
- Effective Java通俗理解(持续更新)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
- JAVA提高五:注解Annotation
今天我们学习JDK5.0中一个非常重要的特性,叫做注解.是现在非常流行的一种方式,可以说因为配置XML 比较麻烦或者比容易查找出错误,现在越来越多的框架开始支持注解方式,比如注明的Spring 框架, ...
- Effective Java通俗理解(上)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java深度理解——Java字节代码的操纵
导读:Java作为业界应用最为广泛的语言之一,深得众多软件厂商和开发者的推崇,更是被包括Oracle在内的众多JCP成员积极地推动发展.但是对于 Java语言的深度理解和运用,毕竟是很少会有人涉及的话 ...
- Java枚举类与注解详解——一篇文章读懂枚举类与注解详
目录 一.枚举类 ① 自定义枚举类 ② enum关键字定义枚举类 ③ enum 枚举类的方法 ④ enum 枚举类实现接口 二.注解 ① 生成文档相关注解 ②注解在编译时进行格式检查 ③注解跟踪代码的 ...
- 深入理解Spring注解机制(一):注解的搜索与处理机制
前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...
随机推荐
- 8168开发之---1g内存换成512M的内存映射配置
最近在帮新来同事调式内存分配,起初是将config.bld 中的内存在标配的基础上减少sr1,和tiler 将dsp从9m增加到16m,然后编译通过, 可是在加载的时候卡住了,init.sh 过,lo ...
- HDOJ 4923 Room and Moor
用一个栈维护b的值,每次把一个数放到栈顶. 看栈首的值是不是大于这个数,假设大于的话将栈顶2个元素合并.b的值就是这两个栈顶元素的平均值. .. Room and Moor Time Limit: 1 ...
- 在Hierarchy面板隐藏物体
PlantObjPreview.hideFlags = HideFlags.HideInHierarchy;
- WCF基础之序列化
wcf是基于消息进行通信的,这篇就是简单说下序列化引擎是如何将.net object转化为xml消息.一般情况下很少用到这些,你只需定义数据协定之类的或者指定相应的序列化引擎,然后设置相应的特性就好. ...
- [php][随机数]曲线式的随机
数学函数原型: y = max / (x ^ 2) 函数图像(来自google): y = 100 / x ^ (-2) 其中y为随机结果,max为最大值且max>1,x为随机数, 两个参数: ...
- 我的Android进阶之旅------>Android 标签的用法
布局资源文件的根节点可以使用容器控件(如LinearLayout.FrameLayout等),也可以使用非容器控件(如:EditText.TextView等).对于非容器控件,只能在非容器控件标签中放 ...
- 我的Android进阶之旅------>HTTP Header 详解
HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议.HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应.就整个网络资源传 ...
- PAT 1062. 最简分数(20)
一个分数一般写成两个整数相除的形式:N/M,其中M不为0.最简分数是指分子和分母没有公约数的分数表示形式. 现给定两个不相等的正分数 N1/M1 和 N2/M2,要求你按从小到大的顺序列出它们之间分母 ...
- PAT 1052. 卖个萌 (20)
萌萌哒表情符号通常由“手”.“眼”.“口”三个主要部分组成.简单起见,我们假设一个表情符号是按下列格式输出的: [左手]([左眼][口][右眼])[右手] 现给出可选用的符号集合,请你按用户的要求输出 ...
- linux c编程:进程控制(一)
一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同 ...