干货系列之java注解

前言

java反射和注解在java里面很重要,但是很多人对这方面的知识理解不是很好,我来说说我自己对java反射和注解的理解,这两块内容本来应该出在一个博客文章里面讲解,但是由于我的java反射说的内容有点小多,然后我就分开将讲解一下。

目录

  1. 注解的概念
  2. 注解的类别
  3. 注解用法
  4. 通过反射获取注解
  5. 反射注解一起使用拼写SQL语句实战演练

注解的概念

java注解:

比较官方的说法:

从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值。

说说我的理解

注解就是Annotation,相信不少人也和我之前一样以为和注释一样,是一段辅助性的文字,其实注解不是这样的。注解与注释的区别在于,注解可以实现程序的某些功能。

注解是不会影响java程序的运行,不会干扰程序代码的运行。通俗来讲,注解就像一个标签,初学者需要知道他就像一个功能标签,能实现一些功能就行了!入门了再慢慢深入理解。

看下面的例子你就能更好的理解注解了。

注解的类别

  1. java语言提供的注解
  2. 元注解
  3. 其他注解

java语言提供的注解

1.Override

学过java你就知道,你肯定见过这种

@Override
public Object clone() throws CloneNotSupportedException {}

没错,@Override就是一个java提供的注解。当你要重写父类的方法是需要用到这个注解。

2.@Deprecated

这个注解你能看到的时间比较少,但是你应该见过类似的,编译一个java程序时,编译器可能会提示你你使用了一个过时的方法(idea会),或者过时的类,过时的成员变量。

3.@SuppressWarnings

这个注解的意思是:阻止编译器的警告,上一个注解说到@Deprecated会提示你使用过时方法等的一个警告,当你使用了这个注解之后就不会有这种提示了!这个注解需要一个参数,参数都是提前设计好了的。

参数如下

  • deprecation 使用了过时的类或方法的警告
  • unchecked 执行了未检查的转换时的警告,如使用集合时未指定泛型
  • fallthrough :当在switch语句使用时发生case穿透
  • path 在类路径,源文件路径等中有不存在路径的警告
  • serial 当在可序列化的类上缺少serialVersionUID定义时的警告
  • finally 任何finally子句不能完成时的警告
  • all 关于以上所有情况的警告

元注解

所谓元注解就是注解的注解,虽然说这些注解也是java语言提供的,但是他不同于上面说的哪几种注解,上面的几种注解也是由元注解组成的。他们的源代码里面包含了元注解。

元注解有哪些呢?

- @Target:注解的作用目标
- @Retention:注解的生命周期
- @Documented:注解是否应当被包含在 JavaDoc 文档中
- @Inherited:是否允许子类继承该注解

这4个值java8之前的元注解,在java8又新增了一个

@Repeatable 元注解,表示被修饰的注解可以用在同一个声明式或者类型加上多个相同的注解(包含不同的属性值)

我们详细说一下这些注解都是什么意思

1.@Target 注解的作用目标

具体的作用目标有以下几个

- ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上

- ElementType.FIELD:允许作用在属性字段上

- ElementType.METHOD:允许作用在方法上

- ElementType.PARAMETER:允许作用在方法参数上

- ElementType.CONSTRUCTOR:允许作用在构造器上

- ElementType.LOCAL_VARIABLE:允许作用在局部变量上

- ElementType.ANNOTATION_TYPE:允许作用在注解上

- ElementType.PACKAGE:允许作用在包上

以上都是这个注解的参数

可能有人会问作用目标是什么?就是说我声明的这个注解可以用在那个地方,比如说@Override,是不是只能用在重写的方法上面。如果你学了springboot的话,里面的很多注解都是可以使用在类上面也可以使用在方法上面。

2.@Retention 注解的生命周期

什么意思?注解本身是不会影响正常逻辑程序的运行的,然后这个注解的生命周期指的是我声明的这个注解会保留到什么阶段,具体的参数如下:

- RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件,会被编译器丢弃
- RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件,会被java虚拟机丢弃
- RetentionPolicy.RUNTIME:永久保存,可以反射获取到对应的注解

3.@Documented 注解是否应当被包含在 JavaDoc 文档中

这个倒没有什么好说的,就是标注被修饰这个注解包含在JavaDoc文档中。

4.@Inherited 是否允许子类继承该注解

简单点说,子类继承父类时,如果父类的注解有@Inherited标识的注解,子类继承过来的时候也会自动继承@Inherited标识的注解。

但是在接口继承的时候,子类不会继承任何@Inherited标识的注解。

5.@Repeatable

在需要对同一种注解多次使用时,往往需要借助@Repeatable。比如说,现在有一篇文章,这篇文章需要添加多个标签,这些标签就相当于注解,但是这个标签只是内容不同,这时候就需要使用到这个注解了。

其他注解

所谓的其他注解就是第三方注解,比如说很火的springboot,它提供了很多的注解,可以替代一些配置文件,告诉这个框架有这个注解是需要提供哪些功能。比如说@Controller,@RequestMapping,@Service等。

注解用法

讲了半天,可能你还是一脸懵逼,你只讲概念,怎么用?

下面就来介绍这个注解怎么用,主要是讲解注解的声明用法。

1.注解声明

public @interface Entity {

}

这个和声明接口很类似,只是在前面多了一个@

具体怎么用,我们用一个例子来讲解

@Target(ElementType.TYPE)//允许声明的注解修饰在接口,类,枚举上面
@Retention(RetentionPolicy.RUNTIME)//代码运行期间一直保存注解,可以通过反射获取
public @interface Entity {
//表名,注解的参数,默认为空
public String tableName() default "";
//中文名称
public String cnName() default ""; }

解释一下注解的参数声明

第一个参数定义参数为String类型,设置default 默认值,表示这个不是必须的,在使用注解的时候没有填写这个参数不会报错,他会使用默认值。

声明好注解之后,我们将这些注解运用到一个实体类上面。

再来一个声明的作用在属性上面的注解。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
//属性的名称
public String fieldName() default "";
//属性的属性中文名称
public String fieldCnName() default "";
//属性的类型
public String Type() default "String";
}

然后我们将这两个注解运用到实体类Student上面。

@Entity(tableName = "student",cnName = "学生表")
public class Student {
@Column(fieldCnName = "姓名",fieldName ="name")
private String name;
@Column(fieldCnName = "年龄",fieldName = "age",Type = "Integer")
private Integer age;
@Column(fieldCnName = "性别",fieldName = "sex")
private String sex;
}

set,get方法没有贴上来。

具体的用法就是这样了。然后我们说说注解与反射的关系,怎么用反射获取注解。

通过反射获取注解

不会反射的请看上一篇文章,8000字为你讲懂反射,然后再回来看这篇注解的文章。

上代码直接

	//获取Class类
Class clazz = Student.class; //获取类上面的注解
Entity entity = (Entity) clazz.getAnnotation(Entity.class);
System.out.println(entity.cnName()+entity.tableName()); //获取所有该类声明的属性
Field fields[] = clazz.getDeclaredFields(); for (Field field:fields){
//获取对应属性上面的注解
Column column = field.getAnnotation(Column.class);
System.out.println(column.fieldCnName());
}

这个运行结果是

学生表student
姓名
年龄
性别

很简单是不是。懂了吗?懂了的话关注走一波?精彩美文每天为你推送,喜欢手机看文章的还可以(wx search 全栈学习笔记)!

反射注解一起使用拼写SQL语句实战演练

其实这一部分你懂反射和注解就会了,通过反射和注解你可以实现一个简单的万能的增删改查。贴个新增的SQL语句代码吧!

//insert into student_test(student_id,student_name,student_sex) values (1,"Jack","男")
StringBuilder sql = new StringBuilder();
Class clazz = object.getClass();
sql.append("insert into ");
//获取类上面的注解
Entity entity = (Entity) clazz.getAnnotation(Entity.class);
sql.append(entity.tableName()); sql.append("(");
Field[] fields = clazz.getDeclaredFields();
for(Field field:fields){
sql.append(field.getAnnotation(Column.class).fieldName()).append(",");
}
sql.deleteCharAt(sql.length()-1);
sql.append(")");
sql.append(" values (");
for(Field field:fields){
field.setAccessible(true);
Object value = field.get(object);
if(value.getClass().equals(String.class)){
sql.append("\"").append(value).append("\"").append(",");
}else {
sql.append(value).append(",");
}
}
sql.deleteCharAt(sql.length()-1);
sql.append(")");
System.out.println(sql.toString());
return sql.toString();

结语:觉得文章不错的,带上原文链接,欢迎转发,如果你发现文章中有错误可以评论或者私信我,及时修改!(wx search 全栈学习笔记)精彩美文每天为你推送!

干货系列之java注解的更多相关文章

  1. 夯实Java基础系列15:Java注解简介和最佳实践

    Java注解简介 注解如同标签 Java 注解概述 什么是注解? 注解的用处 注解的原理 元注解 JDK里的注解 注解处理器实战 不同类型的注解 类注解 方法注解 参数注解 变量注解 Java注解相关 ...

  2. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  3. Java多线程干货系列—(四)volatile关键字

    原文地址:http://tengj.top/2016/05/06/threadvolatile4/ <h1 id="前言"><a href="#前言&q ...

  4. 【转】Spring Boot干货系列:(一)优雅的入门篇

    转自Spring Boot干货系列:(一)优雅的入门篇 前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做 ...

  5. 【转】Spring Boot干货系列:(二)配置文件解析

    转自:Spring Boot干货系列:(二)配置文件解析 前言 上一篇介绍了Spring Boot的入门,知道了Spring Boot使用"习惯优于配置"(项目中存在大量的配置,此 ...

  6. 【转】Spring Boot干货系列:(三)启动原理解析

    前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏.所以这次博主就跟你们一起一步步揭开Sprin ...

  7. Spring Boot干货系列:(六)静态资源和拦截器处理

    Spring Boot干货系列:(六)静态资源和拦截器处理 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类We ...

  8. Spring Boot干货系列:(四)Thymeleaf篇

    Spring Boot干货系列:(四)Thymeleaf篇 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 Web开发是我们平时开发中至关重要的,这里就来介绍一下Spring Boo ...

  9. Spring Boot干货系列:(二)配置文件解析

    Spring Boot干货系列:(二)配置文件解析 2017-02-28 嘟嘟MD 嘟爷java超神学堂   前言 上一篇介绍了Spring Boot的入门,知道了Spring Boot使用“习惯优于 ...

随机推荐

  1. js大作业(0)

    DAY1:在看HTML5游戏开发实战.手写了一遍乒乓球.自己玩了半小时.实话讲,和本科学的MFC差别不大.通过setInterval函数获取用户的输入 从而允许多用户操作.parseInt把字符串化为 ...

  2. EventBus 及一些思考

    EventBus 是 Android 开发的一种常用框架,其解耦的思维令人赞叹 从特性上来讲,其与 Android SDK中的BroadcastReceiver很像,二者都是注册,发送事件,反注册,都 ...

  3. optparse(命令行参数解析工具)

    在用Python做自动化的时候,命令行的解析一定是少不了的,有很多命令行解析工具库,其中Python内建的一个库optparse,还是比较好用的 1.贴代码并注释 # coding=UTF-8 fro ...

  4. 从输入URL到页面展示

    当我们输入 URL 并按回车后,浏览器会对 URL 进行检查,首先判断URL格式,比如是ftp http ed2k等等,我们这里假设这个URL是http://hellocassie.cn,那么浏览器会 ...

  5. 前端实现html转pdf方法总结

    最近要搞前端html转pdf的功能.折腾了两天,略有所收,踩了一些坑,所以做些记录,为后来的兄弟做些提示,也算是回馈社区.经过一番调(sou)研(suo)发现html导出pdf一般有这几种方式,各有各 ...

  6. p2.js 与 createjs 的组合应用

    开始前简单说下其他几款js物理引擎 box2d老牌,功能全面,但是效率低下,移动端基不用考虑的 matterjs  效率目前我测试下来最高,但是依然还在开发中(好像还很缓慢),目前功能局限,而且有bu ...

  7. vue项目用sha256、md5、base64加密密码

    无论你开发什么样的项目,你可能都会要开发登录.注册.修改密码.忘记密码这些功能,少数项目除外!!要实现这些功能,对于保护用户或者管理员账号密码,这是我们程序员肯定要做的事情.要是用户密码不加密,用明文 ...

  8. mysql数据库远程访问设置方法

    1. 修改方式1代码改表法.  可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库 ...

  9. LSP原则—关于正方形不是长方形

    长方形有二个属性长和宽.并有一个设置长的方法和设置宽的方法,还有一个求面积的方法. 像下面 private int length; private int width; public void set ...

  10. scrapy中间件中使用selenium切换ip

    scrapy抓取一些需要js加载页面时一般要么是通过接口直接获取数据,要么是js加载,但是我通过selenium也可以获取动态页面 但是有个问题,容易给反爬,因为在scrapy中间件mid中使用sel ...