java注解相关介绍与实例

注解:

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

提供了一种原程序中的元素关联任何信息和任何数据的途径和方法

注解介绍

注解如同一种标签,表明对被注解的事物行为的某些角度的评价与解释。
首先来了解一下Java自带的部分常用注解:
@Override:很常见:表示子类对父类方法的重写
@Deprecated:表示已被弃用一个过时的方法等
@Suppvisewarnings:表示阻止警告
@FunctionalInterface:函数式接口注解,

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

还有很多第三方的注解,比如ButterKnife中@BindView便是一个注解。

注解分类

注解也有分类的,按运行机制来划分的话,可分为:

  • 源码注解 :注解只会在源码文件中存在,编译成.class文件时会被编译器丢弃
  • 编译时注解:在源码和.class文件中都存在如@Override、@Suppvisewarunings都属于此类
  • 运行时注解:JVM运行时也会保留注解,可通过反射获取注解信息,如@Deprecated

其中还有元注解,表示对注解的注解,比如以上三种分类,都对应元注解中的@Retention注解,有三类值:

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,

    /**
     * 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
}

下面来具体介绍元注解:元注解有5种,如下
@Retention、@Documented、@Target、@Inherited、@Repeatable。

元注解含义
@Target表示该注解的作用域,指定了注解运用的地方,如变量FILED、方法METHON、类、接口(包括注解)、枚举TYPE、构造方法CONSTRUCTOR、局部变量LOCAL_VARIABLE等
@Retention它的因为意义为保留,说明它的存活时期,表示在什么级别运用该注解,有三种,如上面所说的
@Document与javadoc文档相关,将该注解中的元素保留到javadoc中
@Inherited英文意义为继承,表示子类可以继承父类的注解,自承父业的意思,哈哈
@Repeatable英文意义为可重复的,表示注解能运用多次,相当于可以重复使用该注解

下面来使用一下自定义注解:
先定义一个Description,表示对一个人的描述

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {//注解需要使用@interface关键字定义
//如果注解只有一个成员,则需名为value()
//成员类型是受限制的,合法类型包括基本变量类型和String,Class,Annotation,Enum
    String desc();//成员必须要无参数无异常

    String author();

    int age() default 18;//可以使用default指定默认值

}

解析注解

其实我感觉这类不为显式的值,都可以通过反射来获取。
首先创建自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {

    String value();

}

再创建注解所作用的类

@Description("the class Annotation")
public class TestAnnotation {

    @Description("the method Annotation")
    public String name(){
        return null;
    }
}

再进行解析

public static void main(String[] args) throws ClassNotFoundException {
        //1.使用ClassLoader加载类
        Class c = Class.forName("annotation.TestAnnotation");
        //2.找到类上的注解
        boolean isExist = c.isAnnotationPresent(Description.class);//判断是否存在该注解
        if (isExist){
            //3.获取注解实例
            Description description = (Description) c.getAnnotation(Description.class);
            System.out.println(description.value());
        }
    }

输出为:the class Annotation
方法上的注解也是一样的,

//4.找到方法的注解
            Method[] method = c.getMethods();
            for (Method m : method){
                if (m.isAnnotationPresent(Description.class)){
                    System.out.println(m.getAnnotation(Description.class).value());
                }
            }

注解实例

假设一个需求,需要对每个表的字段自动的生成sql查询语句,你要去怎么设计,一个好的方法便是通过注解去获取。
User

@Table("user")
public class User {

    @Column("id")
    private int id;

    @Column("user_name")
    private String userName;

    @Column("nick_name")
    private String nickName;

    @Column("age")
    private int age;

    @Column("city")
    private String city;

    @Column("email")
    private String email;

    @Column("mobile")
    private String mobile;
....省略get,set方法

Table注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {

    String value();

}

Column注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

    String value();

}

SqlUitl生成Sql语句工具类

public class SqlUtil {

    public static String query(Object t) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuilder sb = new StringBuilder();
        //1.获取class
        Class c = t.getClass();
        //2.获取Table名
        if (!c.isAnnotationPresent(Table.class)){
            return "";
        }
        Table table = (Table) c.getAnnotation(Table.class);
        sb.append("select * from ").append(table.value()).append("where 1=1");
        //3.遍历所有字段
        Field[] field = c.getDeclaredFields();
        for (Field f : field){
            //4.处理每个字段对应的sql
                //4.1拿到字段注解值
            if (!f.isAnnotationPresent(Column.class)){
                continue;
            }
            Column column = f.getAnnotation(Column.class);
            String columbName = column.value();
                //4.2拿到字段的名
            String fieldName = f.getName();
                    //获取相应的get方法名
            String MethodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
            Method method = c.getMethod(MethodName);
            Object filedValue = method.invoke(t);
            //4.3拼装成sql
            if (filedValue == null || filedValue instanceof Integer && (Integer) filedValue == 0){
                continue;
            }
            sb.append(" and ").append(columbName);
            if (filedValue instanceof String){
                sb.append("=").append("'").append(filedValue).append("'");
            }else if (filedValue instanceof Integer){
                sb.append("=").append(filedValue);
            }

        }
        return sb.toString();
    }
}

下面便来测试下效果如何

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user = new User();
        user.setId(9);
        user.setUserName("QQW");
        user.setEmail("12156@adas.com");

        System.out.println(SqlUtil.query(user));
    }

输出:select * from userwhere 1=1 and id=9 and user_name='QQW' and email='12156@adas.com'
假如这个时候换另外一个表,现在只需要补上相应的注解即可自动生成,是不是很强大。这也便是注解的作用之一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值