Java注解学习
晨鸣的博客–Java注解学习
注解的分类
按照运行机制分类
注解按照运行机制分类,可分成以下三类
1、源码注解
注解只在源码中存在,编译成.class文件后就不存在了
2、编译时注解
注解在源码及.class文件中都会存在
3、运行时注解
在运行阶段还会起作用,甚至影响程序逻辑
按照来源分类
注解按照来源分类,可分为以下三类
1、来自JDK的注解
2、来自第三方的注解
3、自定义的注解
元注解
元注解是用作注解的注解,一般用在自定义注解时。
JDK自带注解
JDK中自带了一些常见的注解如下:
@Override //子类继承父类方法时,方法的注解
@Deprecated //表示方法已经过时
@SuppressWarnings //用于忽略编译期警告
新建一个Person 接口
public interface Person {
String name();
int age();
@Deprecated //标注sing方法已经过时
void sing();
}
一个Child子类实现Person接口
public class Child implements Person {
@Override
public String name() {
return null;
}
@Override
public int age() {
return 0;
}
@Override
public void sing() {
System.out.println("child is singing!!");
}
}
测试类
public class Test {
@SuppressWarnings("deprecated") //消除警告
public static void main(String[] args){
Person person = new Child();
person.sing();
}
}
第三方注解
以上是Java开发中常用的Spring、Mybatis框架中常用的注解,暂时未学习到。类比Android开发中第三方框架如ButterKnife中也包含许多注解标签,例如@ViewBind、@Onclick等
自定义注解
定义注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
String desc();
String author();
int age() default 18;
}
- 使用@interface 定义注解
- 成员以无参无异常方式声明,若只有一个成员,默认必须定义为 value()
- 可以用default为成员指定一个默认值
- 成员类型是受限的,合法的类型包括原始类型及String,Class,Annotation,Enumeration
- @Target()表示注解的作用域
ElementType.CONSTRUCTOR 构造方法声明
ElementType.FIELD 字段声明
ElementType.LOCAL_VARIABLE 局部变量声明
ElementType.METHOD 方法声明
ElementType.PACKAGE 包声明
ElementType.PARAMETER 参数声明
ElementType.TYPE 类接口
- @Retention()生命周期
RetentionPolicy.SOURCE 只在源码显示,编译时会丢失
RetentionPolicy.CLASS 编译时会记录到.class文件中,运行时忽略
RetentionPolicy.RUNTIME 运行时存在,可通过反射读取- @Inherited 标识性注解,表示允许子类继承,这里的继承是指父类添加类注解,子类只有通过extend继承时可继承注解信息,且只可继承类注解.
- @Documented 生成 javadoc时会包含注解的信息
使用自定义注解
@Description(desc = "this is class Annotation!", author = "AnnUtils")
public class AnnUtils {
@Description(desc = "this is method Annotation!", author = "test", age = 25)
public void test() {
System.out.println("这是测试方法");
}
}
public class AnnTest {
public static void main(String[] args) throws ClassNotFoundException {
//1.使用类加载器加载类
Class c = Class.forName("lcm.ann.AnnUtils");
//2.找到类上面的注解
boolean isExist = c.isAnnotationPresent(Description.class);
if (isExist) {
//3.拿到注解实例
Description d = (Description) c.getAnnotation(Description.class);
System.out.println("dec:" + d.desc() + " author:" + d.author() + " age:" + d.age());
}
//4.找到方法上的注解
Method[] ms = c.getMethods();
for (int i = 0; i < ms.length; i++) {
Method m = ms[i];
boolean isMExist = m.isAnnotationPresent(Description.class);
if(isMExist){
Description md = m.getAnnotation(Description.class);
System.out.println("dec:" + md.desc() + " author:" + md.author() + " age:" + md.age());
}
}
//另一种解析方法
for (int i = 0; i < ms.length; i++) {
Method m = ms[i];
Annotation[] as = m.getAnnotations();
for (Annotation a:as) {
if (a instanceof Description){
Description d = (Description) a;
System.out.println("dec:" + d.desc() + " author:" + d.author() + " age:" + d.age());
}
}
}
}
}
自定义注解小实战
需求:
1. 有一张用户表,字段包括用户ID,用户名,昵称,年龄,性别,所在城市,邮箱,手机号.
2. 方便对每个字段或字段的组合条件进行检索,并打印出SQL语句
思路:
1. 使用自定义注解标注数据库对应实体类
2. 封装一个方法对实体类对象进行解析,并生成SQL语句
定义注解
/**
* ****************************************************************
* Author: LCM
* Date: 2017/4/13 10:20
* Desc: 自定义注解 映射数据库
* *****************************************************************
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
/**
* ****************************************************************
* Author: LCM
* Date: 2017/4/13 10:23
* Desc: 自定义注解 映射数据库表字段
* *****************************************************************
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
使用注解
/**
* ****************************************************************
* Author: LCM
* Date: 2017/4/13 10:30
* Desc: 与数据库字段对应的类
* 通过注解映射数据库
* *****************************************************************
*/
@Table("user")
public class Filter {
@Column("id")
private int id;
@Column("user_name")
private String user_name;
@Column("nick_name")
private String nick_name;
@Column("age")
private int age;
@Column("sex")
private int sex;
@Column("city")
private String city;
@Column("email")
private String email;
@Column("mobile")
private String mobile;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
...
}
测试
/**
* ****************************************************************
* Author: LCM
* Date: 2017/4/13 10:36
* Desc:
* *****************************************************************
*/
public class Test {
public static void main(String[] args) {
Filter f1 = new Filter();
f1.setId(10); //根据ID查询
Filter f2 = new Filter();
f2.setUser_name("Chaman"); //根据用户名进行查询
Filter f3 = new Filter();
f3.setEmail("ll@aa.com,oooo@kk.com,pppp@xx.com"); //根据邮箱进行查询
String sql1 = query(f1);
String sql2 = query(f2);
String sql3 = query(f3);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
}
private static String query(Filter f) {
StringBuilder sb = new StringBuilder();
//获取到Class对象
Class c = f.getClass();
//获取Table的值
boolean isTableExist = c.isAnnotationPresent(Table.class);
if (!isTableExist) {
return null;
}
Table table = (Table) c.getAnnotation(Table.class);
String tableName = table.value();
sb.append("SELECT * FROM ").append(tableName).append(" WHERE 1=1 ");
//获取字段
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
boolean isColumnExist = field.isAnnotationPresent(Column.class);
if (!isColumnExist) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//通过反射获取字段的值
String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Object feildValue = null;
try {
Method method = c.getMethod(getMethodName);
feildValue = method.invoke(f);
} catch (Exception e) {
e.printStackTrace();
}
if (feildValue == null || (feildValue instanceof Integer && (Integer) feildValue == 0)) {
continue;
}
sb.append(" AND ").append(columnName);
if (feildValue instanceof String) { //如果字段是String类型,拼接需加''
if (((String) feildValue).contains(",")) {
String[] split = ((String) feildValue).split(",");
sb.append(" in(");
for (String s : split) {
sb.append(s+",");
}
sb.deleteCharAt(sb.length()-1);
sb.append(")");
} else {
sb.append(" = '").append(feildValue).append("'");
}
}
if (feildValue instanceof Integer) {
sb.append(" = ").append(feildValue);
}
}
return sb.toString();
}
}