前言java
java反射和注解在java里面很重要,可是不少人对这方面的知识理解不是很好,我来讲说我本身对java反射和注解的理解,这两块内容原本应该出在一个博客文章里面讲解,可是因为个人java反射说的内容有点小多,而后我就分开将讲解一下。spring
目录sql
java注解:
比较官方的说法:
从JDK5开始,Java增长对元数据的支持,也就是注解,注解与注释是有必定区别的,能够把注解理解为代码里的特殊标记,这些标记能够在编译,类加载,运行时被读取,并执行相应的处理。经过注解开发人员能够在不改变原有代码和逻辑的状况下在源代码中嵌入补充信息。springboot
注解,能够看做是对 一个 类/方法 的一个扩展的模版,每一个 类/方法 按照注解类中的规则,来为 类/方法 注解不一样的参数,在用到的地方能够获得不一样的 类/方法 中注解的各类参数与值。app
说说个人理解框架
注解就是Annotation,相信很多人也和我以前同样觉得和注释同样,是一段辅助性的文字,其实注解不是这样的。注解与注释的区别在于,注解能够实现程序的某些功能。ide
注解是不会影响java程序的运行,不会干扰程序代码的运行。通俗来说,注解就像一个标签,初学者须要知道他就像一个功能标签,能实现一些功能就好了!入门了再慢慢深刻理解。学习
看下面的例子你就能更好的理解注解了。ui
1.Override
学过java你就知道,你确定见过这种idea
@Override public Object clone() throws CloneNotSupportedException {}
没错,@Override就是一个java提供的注解。当你要重写父类的方法是须要用到这个注解。
2.@Deprecated
这个注解你能看到的时间比较少,可是你应该见过相似的,编译一个java程序时,编译器可能会提示你你使用了一个过期的方法(idea会),或者过期的类,过期的成员变量。
3.@SuppressWarnings
这个注解的意思是:阻止编译器的警告,上一个注解说到@Deprecated会提示你使用过期方法等的一个警告,当你使用了这个注解以后就不会有这种提示了!这个注解须要一个参数,参数都是提早设计好了的。
参数以下
所谓元注解就是注解的注解,虽说这些注解也是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语句代码吧!
//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 全栈学习笔记)精彩美文天天为你推送!