感谢原文作者:yejg1212

原文链接

https://www.cnblogs.com/yejg1212/p/3187362.html

https://www.cnblogs.com/yejg1212/p/3188751.html

https://www.cnblogs.com/yejg1212/p/3188791.html

超通俗易懂的注解入门文章:https://blog.csdn.net/shengzhu1/article/details/81271409

Bilibili:https://www.bilibili.com/video/av55440782

Ⅰ. 简单介绍Jave的内置注解(7个:4个元注解)

Java从JDK 5开始引入注解(annotation)。

注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。

注解的功能类似于代码中的注释,所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。

Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。

下面先来看看java中常用的注解。

一、常用注解

① @Override注解

package java.lang;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Override注解表示子类要重写父类的对应方法。

如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

顺便说一句:@override注解在JDK 5环境下只能用于对继承的类的方法的重写,实现接口中的方法不能用@override注解。但是JDK1.6可以。

② @Deprecated注解

package java.lang;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
}

@Deprecated注解表示方法是不被建议使用的。

③ @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();
}

@SuppressWarnings注解表示抑制警告。

例如下面的代码,声明了2个未使用的变量,加上2个@SuppressWarnings来抑制警告。

@SuppressWarnings("unused")
int a=10; @SuppressWarnings({ "rawtypes", "unused" })
List list =new ArrayList();

上面给出了Java自带的几个常用的注解,下面先来了解下代码中出现的诸如@Target,@Retention,@Documented(这些也叫元注解)的意义。

二、元注解

① @Target

@Target 表示该注解用于什么地方,可取的值包括:

  • ElemenetType.CONSTRUCTOR     构造器声明

  • ElemenetType.FIELD          域声明(包括 enum 实例)

  • ElemenetType.LOCAL_VARIABLE    局部变量声明

  • ElemenetType.METHOD         方法声明

  • ElemenetType.PACKAGE        包声明

  • ElemenetType.PARAMETER       参数声明

  • ElemenetType.TYPE          类,接口(包括注解类型)或enum声明

  • ElementType.ANNOTATION_TYPE   注解

② @Retention

@Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:

  • RetentionPolicy.SOURCE       注解将被编译器丢弃
  • RetentionPolicy.CLASS        注解在class文件中可用,但会被VM丢弃
  • RetentionPolicy.RUNTIME       JVM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。

③ @Documented

@Documented 将此注解包含在 javadoc 中

④ @Inherited

@Inherited 允许子类继承父类中的注解


Ⅱ. 自定义注解及注射提取的简单介绍

自定义注解其实很简单,直接上代码:

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
/*
1. 定义注解 Test
2. 注解中含有两个元素 id 和 description
3. description 元素 有默认值 "hello anntation"
*/
public @interface Test {
public int id();
public String description() default "hello annotation";
}

根据上一篇对元注解的解释,我们知道:

  1. 这个注解可以用于方法
  2. JVM运行期间该注解都有效
  3. 该注解包含在 javadoc 中
  4. 该注解允许子类继承

下面看下通过注解我们能取到什么

public class TestMain {
/*
* 被注解的三个方法
*/
@Test(id = 1, description = "hello methodA")
public void methodA() {
} @Test(id = 2)
public void methodB() {
} @Test(id = 3, description = "last method")
public void methodC() {
} /*
* 解析注解,将类被注解方法 的信息打印出来
*/
public static void main(String[] args) {
Method[] methods = TestMain.class.getDeclaredMethods();
for (Method method : methods) {
/*
* 判断方法中是否有指定注解类型的注解
*/
boolean hasAnnotation = method.isAnnotationPresent(Test.class);
if (hasAnnotation) {
/*
* 根据注解类型返回方法的指定类型注解
*/
Test annotation = method.getAnnotation(Test.class);
System.out.println("Test( method = " + method.getName() + " , id = " + annotation.id()
+ " , description = " + annotation.description() + " )");
}
}
}
}

上面的Demo打印的结果如下:

Test( method = methodA , id = 1 , description = hello methodA )
Test( method = methodB , id = 2 , description = hello annotation )
Test( method = methodC , id = 3 , description = last method )

例其实也说明了,我们一般通过反射来取RUNTIME保留策略的注解信息。


Ⅲ. 简单实例

目标:将实体bean保存到数据库

先来定义一个实体注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
String getTableName();
}

这个注解可用在类上,它有一个变量参数getTableName。

其实意义很明显,就是一个实体类对应一张数据库的表,通过Entity注解将类和数据库表名关联起来

那么,通过什么将类的参数和数据库表中的列关联起来呢?再来定义一个注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String getName();
}

有了Column注解,类里面的属性就和表中的列关联起来了。

POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。

EJB是的Enterprise Java Beans技术的简称, 又被称为企业Java Beans。这种技术最早是由美国计算公司研发出来的。

下面来看看POJO中怎么用这两个注解:

@Entity(getTableName = "user")
public class User {
@Column(getName = "user_id")
private String id;
@Column(getName = "user_name")
private String name;
@Column(getName = "user_age")
private int age; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
}
}

通过Entity和Column注解,就将一个实体bean和一张数据库表连接起来了。很多ORM映射就是采取这种方式实现的。

最后,来感受一下注解给我们带来的便利,来个方法见证下~~

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement; public class Session {
public static void main(String[] args) {
Session session = new Session();
System.out.println(session.getInsertSql(new User()));
} //在实际项目中,你可以save(obj)方法来保存一个bean
public void save(Object obj) {
// get a connection
//PreparedStatement pstmt = getStatement(con, obj);
//pstmt.execute();
} //得到PreparedStatement
public PreparedStatement getStatement(Connection con, Object obj)
throws Exception {
PreparedStatement pstmt = con.prepareStatement(getInsertSql(obj));
Class<?> c = obj.getClass();
Field[] fs = c.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
fs[i].setAccessible(true);
pstmt.setObject(i + 1, fs[i].get(obj));
}
return pstmt;
} //insert into tableName(ziduan1,ziduan2...) values(?,?...)
public String getInsertSql(Object obj) {
StringBuilder s = new StringBuilder();
s.append("insert into "); Class<?> c = obj.getClass();
String tableName = c.getSimpleName();//类名,不包含包名 User
Entity entity = (Entity) c.getAnnotation(Entity.class);
if (entity != null) {
tableName = entity.getTableName();
}
s.append(tableName).append("(");
Field[] fs = c.getDeclaredFields(); for (int i = 0; i < fs.length; i++) {
String fieldName = fs[i].getName();
Column column = fs[i].getAnnotation(Column.class);
if (column != null) {
fieldName = column.getName();
}
s = i == 0 ? s.append(fieldName) : s.append(",").append(fieldName);
}
s.append(") values").append(getString(fs.length));
return s.toString(); } //得到(?,?,?,...?,?)
private String getString(int length) {
StringBuilder s = new StringBuilder();
s.append("(");
for (int i = 0; i < length; i++) {
s = i == 0 ? s.append("?") : s.append(",?");
}
s.append(")");
return s.toString();
}
}

OK,That’s all!

最新文章

  1. C# 获取SqLite数据库表信息以及获取表内字段信息
  2. javascript中parentNode,childNodes,children的应用详解
  3. Codeforces Round #207 (Div. 1)B(数学)
  4. HDU 3533 Escape (BFS + 预处理)
  5. (3)java棧
  6. android开发 锁屏 真正的锁屏,是go锁屏那种。
  7. c++中构造函数 、析构函数的作用域详解
  8. JS Call()与Apply()
  9. 基于 Android 的 3D 视频示例代码
  10. cookie 的增加,销毁,读取
  11. 队列顺序存储 - 设计与实现 - API函数
  12. Java 领域从传统行业向互联网转型你必须知道的事儿
  13. zsh: command not found: conda的一种解决方法
  14. SQL判断语句
  15. log4j2使用入门(一)
  16. Java_jsp.jstl.Function函数标签库.记录
  17. 搭建Hexo博客(二)-连接github
  18. Ubuntu 关闭触摸板
  19. 【警告】WARN: Establishing SSL connection without server&#39;s identity verification is not recommended.
  20. 单源最短路径算法——Dijkstra算法(迪杰斯特拉算法)

热门文章

  1. 从零开始学springboot-1.创建项目
  2. MongoDB分片设计
  3. 字母 Letters
  4. 论文翻译:2021_Semi-Blind Source Separation for Nonlinear Acoustic Echo Cancellation
  5. springCloudGateway-使用记录
  6. LC 二叉树的最大深度
  7. redis中文乱码问题
  8. 离线环境安装使用 Ansible
  9. 使用nginx访问FastDFS fastdfs nginx
  10. Quay v3.5.1 部署踩坑