Java注解(附具体例子)

什么是注解?

注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值。从JDK5开始,Java增加了对元数据(描述数据属性的信息)的支持。其实说白就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。------百度百科

注解的分类
1、按照运行机制分

  • 源码注解

注解只在源码中存在,编译成.class文件就不存在了

  • 编译时注解

注解在源码和.class文件中都存在,如JDK中自带的@Override@Deprecated@SuppviseWarnings均是编译时注解

  • 运行时注解

在运行时还起作用,甚至会影响运行逻辑的注解,如Spring框架中的@AutoWrite注解

2、按照来源分

  • 来自JDK的注解

限定父类重写方法-@Override:当子类重写父类方法时,子类可以加上这个注解,那这有什么什么用?这可以确保子类确实重写了父类的方法,避免出现低级错误

标示已过时-@Deprecated:这个注解用于表示某个程序元素类,方法等已过时,当其他程序使用已过时的类,方法时编译器会给出警告(删除线)

抑制编译器警告-@SuppressWarnings:被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告,例如修饰一个类,那他的字段,方法都是显示警告

“堆污染”警告-@SafeVarargs:把不带泛型的对象赋给一个带泛型的对象,例List list = new ArrayList();

函数式接口-@Functionallnterface:什么是函数式?如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),接口体内只能声明常量字段和抽象方法,并且被隐式声明为public,static,final。接口里面不能有私有的方法或变量。这个注解有什么用?这个注解保证这个接口只有一个抽象方法,注意这个只能修饰接口

  • 来自第三方的注解

Spring中的@Autowrite

  • 我们自己定义的注解

自定义注解-@MyAnnotation

自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {//@interface注解关键字

    String desc();//成员以无参无异常方式声明

    int age() default 18;//可以用default关键字为成员指定一个默认值
}

@interface为注解的关键字

1、成员类型是受限的,只允许原始数据类型和String、Class、Annotation、Enumeration
2、如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)
3、注解类可以没有成员,没有成员的注解称为标识注解

1、元注解

  • @Target:注解的作用范围
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
public enum ElementType {
    /** 
    类、接口或者一个枚举类型声明 
    Class, interface (including annotation type), or enum declaration
    */
    TYPE,

    /** 
    字段声明(包括枚举类型)
    Field declaration (includes enum constants) 
    */
    FIELD,

    /** 方法声明 Method declaration*/
    METHOD,

    /** 形参声明 Formal parameter declaration*/
    PARAMETER,

    /** 构造函数声明 Constructor declaration*/
    CONSTRUCTOR,

    /** 局部变量声明 Local variable declaration*/
    LOCAL_VARIABLE,

    /** 注解类型声明 Annotation type declaration*/
    ANNOTATION_TYPE,

    /** 包声明 Package declaration*/
    PACKAGE,

    /**
     * 表示该注解能写在类型变量的声明语句中 Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 表示该注解能写在使用类型的任何语句中 Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}
  • @Retention:注解的声明周期
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     * 只在源码显示。编译时会丢弃
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     * 编译时会记录到class中,运行时会忽略
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     * 运行时存在,可以通过反射读取
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
  • @Inherited:允许制类继承
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
  • @Documented:生成javadoc时会包含注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

2、使用自定义注解

例:定义一个JavaBean与数据库之间映射的注解

  • 注解Table(表名)
@Target({ElementType.TYPE})//作用于类
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Documented
public @interface Table {
    String value();//只有一个字段,只能为value
}
  • 注解Column(字段名)
@Target({ElementType.FIELD})//作用于字段
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Documented
public @interface Column {
    String value();//只有一个字段,只能为value
}
  • JavaBean-User
@Table("user_table")//对应数据库中的表名
public class User {
    @Column("user_id")//对应数据库中的字段名
    private String id;
    @Column("user_name")
    private String name;
    @Column("user_sex")
    private String sex;
    @Column("user_age")
    private Integer age;

    public User() {
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  • JavaBean-Department
@Table("department_table")//对应数据库中的表名
public class Department {
    @Column("department_id")//对应数据库中的字段名
    private String id;
    @Column("department_name")
    private String name;
    @Column("department_amount")
    private Integer amount;

    public Department() {
        
    }

    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 Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }
}

  • 生成SQL语句的方法
    /**
     * 获取对象的SQL语句
     *
     * @param obj 对象
     * @return SQL语句
     */
    private static String getSqlStatement(Object obj) {
        StringBuilder sb = new StringBuilder();
        //1、获取对象的class
        Class clazz = obj.getClass();
        //2、获取表名
        boolean isExists = clazz.isAnnotationPresent(Table.class);
        if (!isExists) {
            return null;
        }
        Table table = (Table) clazz.getAnnotation(Table.class);
        String tableName = table.value();
        sb.append("select * from ")
                .append(tableName)
                .append(" where 1 == 1");
        //3、遍历所有字段
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //4、处理每个字段对应的SQL
            //4.1 获取字段的名字
            isExists = field.isAnnotationPresent(Column.class);
            if (!isExists) {
                continue;
            }
            Column column = field.getAnnotation(Column.class);
            String columnName = column.value();
            //4.2 获取字段的值
            String fieldName = field.getName();
            String methodName = "get"
                    + fieldName.substring(0, 1).toUpperCase()//首字母大写
                    + fieldName.substring(1);
            Object fieldValue = "";
            try {
                Method method = clazz.getMethod(methodName);
                fieldValue = method.invoke(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (fieldValue == null ||
                    (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
                continue;
            }
            //4.3 拼接SQL语句
            sb.append(" and ")
                    .append(columnName)
                    .append(" = ");
            if (fieldValue instanceof String) {//当前字段为字符串
                sb.append("'")
                        .append(fieldValue)
                        .append("'");
            } else if (fieldValue instanceof Integer) {//当前字段为整形
                sb.append(fieldValue);
            }//更多数据类型以此类推
        }
        sb.append(";");
        return sb.toString();
    }

测试:

    public static void main(String[] args) {
        User user = new User();//查询一个ID为"10086",名字为"张三",年龄为13的用户
        user.setId("10086");
        user.setName("张三");
        user.setAge(13);
        System.out.println(getSqlStatement(user));
        Department department = new Department();//查询一个ID为"10010",名字为"行政部",人数为100的部门
        department.setId("10010");
        department.setName("行政部");
        department.setAmount(100);
        System.out.println(getSqlStatement(department));
    }

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值