当前位置: 首页 > news >正文

全面解析java注解

一.注解的定义与分类

注解的概念:

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

JDK自带注解:

@Override  代表子类重写父类的方法

@Deprecated  代表该方法已经过时

@SuppressWarning 代表忽略警告Warnings

注解的分类:

  • 源码注解:注解只在源码中存在,编译成.class文件就不存在了
  • 编译时注解:注解在源码和.class文件中都存在(@Override,@Deprecated这些都是)
  • 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解(@Autowired)

注解的代价

凡事有得必有失,注解技术同样如此。使用注解也有一定的代价:

  • 显然,它是一种侵入式编程,那么,自然就存在着增加程序耦合度的问题。
  • 自定义注解的处理需要在运行时,通过反射技术来获取属性。如果注解所修饰的元素是类的非 public 成员,也可以通过反射获取。这就违背了面向对象的封装性。
  • 注解所产生的问题,相对而言,更难以 debug 或定位。

二.自定义注解

1.自定义注解的语法要求

a.使用@interface关键字定义注解

b.成员以无参无异常方式声明

c.可以用default为成员指定一个默认值

d.其中成员类型是受限的,合法的类型包括原始类型及String,Class,Annotation,Enumeration

e.如果注解只有一个成员,则成员名必须为value(),在使用时可以忽略成员名和赋值号(=)

f.注解类可以没有成员,没有成员的注解称为标识注解(例如@Overrride)

//以下成员都是不合法的,因为成员要无参数,无异常
String desc(int a);
String desc() throws Exception;//成员类型为受限的,以下不可以
Map desc();
//语法:
//注解属性只能使用 public 或默认访问级别(即不指定访问级别修饰符)修饰。
[访问级别修饰符] [数据类型] 名称() default 默认值;

元注解:

  • @Target是作用域

  • @Retention生命周期

  • @Inherited 这是一个标识型元注解,即允许继承(默认情况下不是这样)

  • @Documented 生成javadoc时会包含注解

2.使用自定义注解

解析注解:

概念:通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑

public static void main(String[] args){//1.使用类加载器加载类try{Class c=Class.forName("com.ann.test.Child");//2.找到类上面的注解boolean isExist=c.isAnnotation(Description.class);if(isExist){//3.拿到注解实例Description d=(Description)c.getAnnotation(Description.class);System.out.println(d.value());
}//4.找到方法上的注解Method[] ms=c.getMethods();for(Method m:ms){boolean isExist=m.isAnnotation(Description.class);if(isExist){Description d=(Description)m.getAnnotation(Description.class);System.out.println(d.value())}}
}}catch(ClassNotFoundException e){e.printStackTrace();
}
}

三.注解实战

需求:

  1. 有一张用户表,字段包括用户ID,用户名,昵称,年纪,性别,所在城市,邮箱,手机号
  2. 方便的对每个字段或者字段的组合条件进行检索,并打印出SQL
package reflectionandproxy.test;
//1.首先考虑代码如何与数据库进行映射--->Filter和数据库字段相似
@Table("user")
public class Filter {@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;public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = 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;}
}
package reflectionandproxy.test;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {String value();//数据库字段名
}
package reflectionandproxy.test;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)public @interface Table {String value();//表名
}
package reflectionandproxy.test;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Test {public static void main(String[] args) {Filter f1=new Filter();f1.setId(10);//查询ID为10的用户Filter f2=new Filter();f2.setUserName("Tom");//模糊查询用户名为Tom的用户Filter f3=new Filter();f3.setEmail("tom@gmail.com,cat@gmail.com,7777@qq.com");//查询邮箱为其中任意一个//查询sql语句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 f1) {//2.接下来我们就考虑如何实现query方法StringBuilder sb=new StringBuilder();//a.获取到classClass clazz=f1.getClass();//b.获取到table的名字boolean exists = clazz.isAnnotationPresent(Table.class);if(! exists){return null;}Table table= (Table) clazz.getAnnotation(Table.class);String tableName=table.value();sb.append("select * from ").append(tableName).append(" where 1=1");//c.获取到所有的字段Field[] fields=clazz.getDeclaredFields();for (Field field : fields){//4.处理每个字段对应的sql语句//4.1 获取到字段名boolean exists1 = field.isAnnotationPresent(Column.class);if(! exists1){continue;}Column column=field.getAnnotation(Column.class);String columnName=column.value();//4.2 获取字段值String fieldName = field.getName();String getMethodName = "get" + fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);Object fieldValue=null;try {Method getMethod = clazz.getMethod(getMethodName);fieldValue =getMethod.invoke(f1);} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}//4.3拼装sql语句if(fieldValue==null||(fieldValue instanceof Integer && ((Integer) fieldValue).intValue()==0)){continue;}sb.append(" and ").append(columnName).append(" = ").append(fieldValue);}return sb.toString();}
}

控制台输出:

http://www.dtcms.com/a/466469.html

相关文章:

  • 多模态大模型研究国庆简报【2025-10-1~2025-10-10】
  • promise的用法
  • 13年测试经验,性能测试-性能调优分析汇总,一篇汇总...
  • 网站开发组合 所有组合网站建设负责人证明
  • BFS解决最短路径问题
  • DNS 隐私防护与用户画像防范策略
  • 免费的x网站域名上海十大工业设计公司
  • 如何在Android Studio中使用Gemini进行AI Coding
  • 学校网站建设材料惠州抖音推广
  • DIN70121协议解读
  • 网站优化软件常用python编程软件
  • 软件的设计原理
  • petri网学习笔记——(五)第二章 petri网的动态性质
  • 长兴网站制作公司wordpress tag优化
  • Spring Bean 生命周期详解:初始化与销毁方式对比与实践
  • 做交易网站什么开发语言网络工程师
  • DeviceNet 转 Modbus TCP 协议转换在 S7-1200 PLC化工反应釜中的应用
  • 网站建设公司网络服务学美工难吗
  • S29-昆仑触屏串口批量写应用
  • C# 委托(Delegate)
  • 企业单位网站建设内容需要什么saas电商建站系统
  • 【63】OpenCV C++实战篇——用C++实现的直线卡尺工具--自选找线方向(从左到右、从右到左、从上到下、从下到上)
  • 做网站你们用什么浏览器如何免费建立个人网站
  • 《金钱心理学》读后感
  • 临沂网站设计建设wordpress 下拉菜单设置
  • PyTorch Transformers| Azure
  • 2.c++面向对象(二)
  • 苍穹外卖-Apache ECharts与数据统计
  • 合肥企业建站系统wap网站浏览器
  • python进阶_Day4