java注解的使用——含例子

本文深入讲解Java注解的概念、分类及应用案例。介绍注解如何为程序元素附加元数据,探讨不同类型的注解及其用途,并通过实例展示如何利用注解实现类与数据库表的映射。

一、解释注解
Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。

  Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。从某些方面看,annotation就像修饰符一样被使用,并应用于包、类 型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在Annotation的“name=value”结构对中。

  Annotation的成员在Annotation类型中以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。在此有一个特定的默认语法:允许声明任何Annotation成员的默认值:一个Annotation可以将name=value对作为没有定义默认值的Annotation成员的值,当然也可以使用name=value对来覆盖其它成员默认值。这一点有些近似类的继承特性,父类的构造函数可以作为子类的默认构造函数,但是也可以被子类覆盖。

  Annotation能被用来为某个程序元素(类、方法、成员变量等)关联任何的信息。需要注意的是,这里存在着一个基本的规则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。另外,尽管一些annotation通过java的反射api方法在运行时被访问,而java语言解释器在工作时忽略了这些annotation。正是由于java虚拟机忽略了Annotation,导致了annotation类型在代码中是“不起作用”的; 只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。本文中将涵盖标准的Annotation和meta-annotation类型,陪伴这些annotation类型的工具是java编译器(当然要以某种特殊的方式处理它们)。
二、注解分类
(1)、按照运行机制分为
源码注解:注解只在源码中存在,编译成class就没有了
编译时注解:注解在源码和.class文件中都存在(如:JDK内置系统注解)
运行时注解:注解在运行还起作用,甚至会影响运行逻辑的注解(如:Spring中@Autowried)
(2)、按照来源
JDK内置系统注解

@Override 用于修饰此方法覆盖了父类的方法;
@Deprecated 用于修饰已经过时的方法;
@suppressWarings("deprecation") 用于通知java编译器忽略特定的编译警告。

元注解

@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD})
// Target 注解的作用域   CONSTRUCTOR 构造方法声明,FIELD 字段声明,LOCAL_VARIABLE 局部变量声明 ,METHOD 方法声明,PACKAGE 包声明,PARAMETER 参数声明,TYPE 类接口。
@Retention(RetentionPolicy.RUNTIME)
//Retention 生命周期 SOURCE 只在源码显示,编译时会丢弃,CLASS 编译时会记录到class中,运行时忽略,RUNTIME 运行时存在,可以通过反射读取。
@Inherited 
//Inherited 允许子类继承
@Documented 
//Documented 生成javadoc的时候包含注解

自定义注解
1.成员类型是受限的,合法的类型包括原始类型及String,Calss,Anootation,Enumreation
2.如果注解已有一个成员,则成员名必须取名为Vaue(),在使用的时可以忽略成员名和赋值号(=)
3.注解类可以没有成员,没有成员的注解称为标识注解

public @interface Description{//使用@interface关键字注解
    String name();//成员以无参无异常方式声明
    String author();
    int age() default 19;//可以用default为成员变量指定一个默认值
    }

第三方注解
springmvc mabatis 等框架的注解

三、例子
功能: 定义一个java 实体类user,通过注解和数据库一张表对应
并且生成sql语句

1、定义Table注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

2、定义数据库列名注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}

3、定义User实体类 和 数据库表对应

@Table("t_user")
public class User {
    @Column("user_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;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

}

4、测试类

public class Test {
    public static void main(String[] args) {

        User user1 = new User();
        user1.setId(0001);//查询ID为0001的用户
        user1.setNickname("繁华");//查询昵称为繁华的用户

        User user2 = new User();
        user2.setUsername("Jack");//查询用户名为Jack的用户
        user2.setAge(18);//查询年龄为18的用户

        User user3 = new User();
        user3.setEmail("lian@sina.com,jiang@qq.com");//查询邮箱为其中任意一个的用户

        String sql1 = query(user1);
        String sql2 = query(user2);
        String sql3 = query(user3);

        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);
    }

    private static String query(User user){
        StringBuilder sb = new StringBuilder();
        //1.获取到Class
        Class< ?> class1 = user.getClass();
        //2.获取到table的名字
        boolean flag1 = class1.isAnnotationPresent(Table.class);
        if(!flag1){
            return null;
        }
        Table table = (Table)class1.getAnnotation(Table.class);
        String tableName = table.value();
        sb.append("select * from ").append(tableName).append(" where 1=1");
        //3.遍历所有的字段
        Field[] fields = class1.getDeclaredFields();
        for (Field field : fields) {
            //4.处理每个字段对应的sql
            //拿到字段名
            boolean flag2 = field.isAnnotationPresent(Column.class);
            if (!flag2) {
                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 fieldValue = null;
            try {
                Method getMethod = class1.getMethod(getMethodName);
                fieldValue = getMethod.invoke(user);
            } catch (Exception e) {
                e.printStackTrace();
            }

            //拼装sql
            if(fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue == 0)){
                continue;
            }
            sb.append(" and ").append(columnName);
            if(fieldValue instanceof String){
                if(((String)fieldValue).contains(",")){
                    String[] values = ((String)fieldValue).split(",");
                    sb.append(" in(");
                    for (String value : values) {
                        sb.append("'").append(value).append("'").append(",");
                    }
                    sb.deleteCharAt(sb.length()-1);
                    sb.append(")");
                }else {
                    sb.append(" = ").append("'").append(fieldValue).append("'");
                }
            }else if(fieldValue instanceof Integer) {
                sb.append(" = ").append(fieldValue);
            }

        }
        return sb.toString();
    }

}


select * from t_user where 1=1 and user_id = 1 and nick_name = '繁华'
select * from t_user where 1=1 and user_name = 'Jack' and age = 18
select * from t_user where 1=1 and email in('lian@sina.com','jiang@qq.com')

参考博文:https://blog.youkuaiyun.com/c1481118216/article/details/52911263
https://blog.youkuaiyun.com/Ssunsets/article/details/51042494

### Java 注解使用方法和示例 #### 什么是注解注解(Annotation)是一种元数据形式,它提供了关于程序代码的信息,但并不直接影响程序本身的运行。它可以应用于包、类、构造函数、方法、变量等。 --- #### 注解的基本特性 注解本身不会改变程序的功能,但它可以被其他工具或框架读取并执行特定的操作。例如,在编译阶段通过注解处理器生成额外的代码或者在运行时动态修改行为[^1]。 --- #### 自定义注解的语法 要创建自定义注解,需使用 `@interface` 关键字。以下是其基本结构: ```java public @interface MyAnnotation { String value() default ""; // 默认值可选 String name(); // 属性名称 int age(); // 属性年龄 String[] roles() default {}; // 数组类型属性 } ``` 此例子展示了如何定义一个带有多种属性类型的注解,包括字符串、整数以及字符串数组[^1]。 --- #### 使用自定义注解 一旦定义好了一个注解,就可以像下面这样将其应用到类、方法或其他元素上: ```java @MyAnnotation(value = "测试", name = "张三", age = 25, roles = {"admin", "user"}) public void someMethod() { // 方法实现 } // 如果只有一个名为 'value' 的属性,则可以直接省略属性名 @MyAnnotation("测试") public void anotherMethod() { // 方法实现 } ``` 当仅有一个 `value` 属性需要赋值时,允许简化书写方式[^1]。 --- #### 处理注解的方式 处理注解可以通过两种主要途径完成:**编译期处理** 和 **运行时反射机制**。 ##### 编译期处理 某些情况下可以在编译期间利用注解来增强代码质量。比如 JDK 提供的标准注解之一——`@Override`,用来确保子类正确覆盖了父类中的某个方法;如果未找到匹配的方法签名,则会抛出错误提示给开发者[^3]。 另一个典型场景涉及正则表达式的验证逻辑。如下所示的是基于正则表达式模式匹配的例子[^2]: ```java import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { String text = "ababccc"; Pattern greedyPattern = Pattern.compile("ab.*c"); Matcher matcherGreedy = greedyPattern.matcher(text); while (matcherGreedy.find()) { System.out.println(matcherGreedy.group()); } Pattern nonGreedyPattern = Pattern.compile("ab.*?c"); Matcher matcherNonGreedy = nonGreedyPattern.matcher(text); while (matcherNonGreedy.find()) { System.out.println(matcherNonGreedy.group()); } } } ``` 这里分别演示了贪婪与懒惰量词的区别效果。 ##### 运行时处理 为了能够在应用程序启动之后仍然访问这些标注信息,我们需要借助于 Java 反射 API 来获取它们。这通常要求我们在声明注解的时候指定保留策略为 RUNTIME: ```java import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface RuntimeAnnotation { String message(); } ``` 随后我们便能编写一段简单的单元测试去检索此类元数据: ```java public class ReflectionDemo { @RuntimeAnnotation(message="这是一个运行时期间可用的注解实例") public void annotatedMethod(){} public static void main(String[] args)throws Exception{ Class<ReflectionDemo> clazz=ReflectionDemo.class; for(java.lang.reflect.Method method :clazz.getDeclaredMethods()){ if(method.isAnnotationPresent(RuntimeAnnotation.class)){ RuntimeAnnotation annotation= method.getAnnotation(RuntimeAnnotation.class); System.out.println(annotation.message()); } } } } ``` 上述代码片段中体现了如何提取由用户自定義之運行時註釋所提供的資訊[^4]。 --- #### 常见标准注解及其用途 除了前面提到过的几个外,还有许多其他的预置选项可供选用,如[@Deprecated](https://docs.oracle.com/javase/tutorial/java/annotations/basics.html),用于标记那些不推荐再继续使用的API组件;又或者是 [@SuppressWarnings]("http://tutorials.jenkov.com/java/suppresswarnings.html") ,旨在抑制不必要的告警消息输出等等[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值