Java注解学习

3 篇文章 0 订阅
1 篇文章 0 订阅

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;

}


  1. 使用@interface 定义注解
  2. 成员以无参无异常方式声明,若只有一个成员,默认必须定义为 value()
  3. 可以用default为成员指定一个默认值
  4. 成员类型是受限的,合法的类型包括原始类型及String,Class,Annotation,Enumeration
  5. @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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值