19_注解

文章目录

  • 注解
    • 注解的作用
    • 注解的语法
    • 注解的使用
  • 元注解
  • 注解处理器
    • 案例
  • 注解VS配置文件
  • 注解的应用

注解

  • Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理
  • 可以把Annotation理解为一个标签
  • 注解是不允许继承

注解的作用

  • 通过使用Annotation,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充信息
  • Annotation就像修饰符一样被使用,可用于修饰构造器方法成员变量参数…,这些信息被存储在Annotation的“属性名=属性值”对中。

注解 VS 注释

  • 相同点
    • 都是用来传递额外信息的
  • 不同点
    • 注解可以参与编译,注释不行
    • 注解有使用范围,注释没有(想咋写咋写)
    • 注解作为一种数据类型,跟class interface具有同等地位

注解的语法

权限修饰符 @interface 注解名字{
    // 注解体定义
    属性类型 属性名();
    属性类型 属性名();
    属性类型 属性名();
    ......
}

属性类型:
基本数据类型
String类型
Class类型
注解类型
枚举类型
以及以上类型的数组形式

eg:

public @interface MyAnnotation {
    int a1();

    double a2();

    String a3();

    Class a4();

    MyAnnotation2 a5();
    
    String[] str();
    
    Season a6();
}

@interface MyAnnotation2{
    
}

enum Season{
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER
}

注解的使用

@注解名(属性1=属性值,属性2=属性值)

注意事项:

  • 每个属性都要赋值

  • 可以不赋值,但是要有默认值, default

  • 数组形式赋值 {}

  • 如果只有1个属性, 名字叫value, 可以简化赋值

  • 如果属性类型是引用类型, 不能是null

eg:


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

    }

    @MyAnno0(hobby = {"football", "basketball", "tennis"})
    @MyAnno1("zs")
    public static void func() {

    }
}

@interface MyAnno0 {
    // 注解体
    int age() default 0;

    String name() default "zs";

    String[] hobby();
}

@interface MyAnno1 {
    // 注解体
    String value();
}


元注解

  • 描述注解的注解(注解的注解)
  • 元数据 meta data

常用元注解:

  • @Retention元注解,来定义我们自己定义的注解的保留级别

    • RetentionPolicy.RUNTIME

    • RetentionPolicy.CLASS 默认

    • RetentionPolicy.SOURCE

  • @Target元注解,注解可以作用的目标

    • 对于注解而言,可以作用的目标:

        1. 整个类 ElementType.TYPE
        1. 成员变量 ElementType.FIELD
        1. 构造方法 ElementType.CONSTRUCTOR
        1. 成员方法 ElementType.METHOD

eg:

在这里插入图片描述


注解处理器

eg:


public class Demo {
    public static void main(String[] args) 
            throws ClassNotFoundException, NoSuchMethodException {
        // 获取字节码文件对象
        Class<?> c = Class.forName("com.csdn.Demo");

        // 得到方法对象
        Method loginMethod = c.getDeclaredMethod("login");

        // 判断方法上面是否使用注解了
        boolean annotationPresent = loginMethod.isAnnotationPresent(Login.class);

        if(annotationPresent){
            // 获取注解实例
            Login loginAnnotation = loginMethod.getAnnotation(Login.class);
            // 获取注解信息
            String password = loginAnnotation.password();
            String name = loginAnnotation.name();
            // 打印
            System.out.println("password = " + password);
            System.out.println("name = " + name);
        }
        else{
            System.out.println("未使用注解");
        }
    }
    @Login
    public static void login(){

    }
}

// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Login{
    // 属性值
    String name() default "admin";

    String password() default "admin";
}

案例

定义2个注解 :

  • AgeLimit 属性 maxAge minAge

  • NameLimit 属性 length

定义学生类Student 年龄18-25之间 名字长度不超过5

eg:


StudentFactory自己定义的类:
public class StudentFactory {
    static Class studentUtils;

    static {
        try {
            studentUtils = Class.forName("com.cskaoyan.Demo0112.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 提供一个获取学生对象的方法
    public static Student getInstance(String name, int age)
            throws NoSuchFieldException, NoSuchMethodException,
            InvocationTargetException,
            InstantiationException, IllegalAccessException {
        // 通过字节码文件获取对象

        // 判断名字
        judgeName(name);

        // 判断年龄
        judgeAge(age);

        // 获取构造方法
        Constructor declaredConstructor = 
        studentUtils.getDeclaredConstructor(String.class, int.class);

        // 破解
        declaredConstructor.setAccessible(true);

        // newInstance 创建对象
        Student student = (Student) declaredConstructor.newInstance(name, age);

        // 最终返回一个学生对象
        return student;
    }

    private static void judgeAge(int age) throws NoSuchFieldException {
        // 获取age成员变量对象
        Field ageField = studentUtils.getDeclaredField("age");
        // 是否使用注解
        boolean annotationPresent = ageField.isAnnotationPresent(AgeLimit.class);
        if (annotationPresent) {
            // 获取注解实例
            AgeLimit ageLimit = ageField.getAnnotation(AgeLimit.class);
            // 拿到注解信息
            int min = ageLimit.minAge();
            int max = ageLimit.maxAge();
            // 是否在范围内
            if (age < min || age > max) {
                throw new IllegalArgumentException("age is illegal");
            }
        }
    }

    private static void judgeName(String name) throws NoSuchFieldException {
        // 获取name成员变量
        Field nameField = studentUtils.getDeclaredField("name");
        // 是否使用注解
        boolean annotationPresent = nameField.isAnnotationPresent(NameLimit.class);
        if (annotationPresent) {
            // 获取注解实例
            NameLimit namelimit = nameField.getAnnotation(NameLimit.class);
            // 拿到注解信息
            int length = namelimit.length();
            // 是否在范围内
            if (name.length() > length) {
                throw new IllegalArgumentException("name is illegal");
            }
        }
    }
}




main函数:
public class Demo {
    public static void main(String[] args)
            throws NoSuchFieldException, InvocationTargetException,
            NoSuchMethodException, InstantiationException,
            IllegalAccessException {
        StudentFactory.getInstance("zs",18);

        StudentFactory.getInstance("ww",1);
    }
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface AgeLimit{
    int maxAge() default 25;
    int minAge() default 18;
}

@interface NameLimit{
    int length();
}

class Student{
    @NameLimit(length = 5)
    String name;
    @AgeLimit
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

注解VS配置文件

配置文件
优点:可配置,不用改源码。管理方便
缺点:不直观,开发效率低

注解
优点:直观开发效率高
缺点:硬编码,修改之后需要重新编译运行,难以和代码分开独立管理

注解的应用

SE :

  • @Test
  • @Override(提供一个额外的信息,方法是重写父类中的方法)
  • @Deprecated(提供一个额外的信息,方法过时了)
  • @FunctionalInterface

EE :

  • @WebService

框架

  • @AutoWired
  • @Service
  • @Mapping
  • @Data
  • @Parm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/313991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发笔记(一):ArkTS概述及声明式UI的使用

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 ArkTS在TS的基础上主要扩展了如下能力&#xff1a; 基本语法&#xff1a;ArkTS定义…

C++内存管理机制(侯捷)笔记3

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 第三讲&#xff1a;malloc和…

波动,热传导,扩散方程建立

数学物理方程是从自然科学的各个领域和工程技术领域中导出的偏微分方程和积分方程.在这些以偏微分方程为基础的数学模型中&#xff0c;二阶线性偏微分方程中的三个典型方程与定解条件的建立、解法及其应用&#xff0e;描述振动和波动过程的波动方程、描述输运过程的热传导&…

【笔记】Blender4.0建模入门-1、2

Blender入门 ——邵发 1.1 课程介绍 Blender&#xff0c;一款3D建模软件&#xff0c;小乔、免费、全流程 常见的3D建模软件&#xff1a; - 3DsMax/Maya/Blender/Cinema4D/ZBrush...游戏影视 - Proe/Solidworks/Inventor/UG...工业建模 - SketchUp/Rhino/Revit...建筑设计 …

想要简化重复订单吗?不妨考虑一揽子采购订单

企业想提高采购流程效率&#xff0c;简化大批量采购是一个很好的开始。财务、会计和采购部门通过系统化订购大量物品&#xff08;如纸张、打印机墨水和墨粉、清洁用品、纸制品和其他易重复采购的消耗品&#xff09;可以节省时间和金钱。借助正确的采购订单&#xff08;PO&#…

俩万字详解C++STL期末复习知识点(C++STL课本源码私信可得)

邸老师复习建议 复习注意事项 1 不考死记硬背的题&#xff0c;比如名词解释。 2 选择题重点考核宏观性、综合性的问题&#xff0c;比如&#xff1a;把电话通讯录存入容器&#xff0c;该选哪一个容器&#xff1f; 3 选择题重点考核理解性的问题&#xff0c;比如&#xff0c;…

C语言——(printf和scanf介绍)

一.printf 1.基本用法 printf&#xff08;&#xff09;的作用是将参数文本输出的屏幕。如下&#xff1b; 2.占位符 printf&#xff08;&#xff09;可以在输出文本中指定占位符 &#xff0c;“占位符”&#xff0c;也就是这个位置可以用其他值代入。 如&#xff1a; …

竞赛保研 基于深度学习的视频多目标跟踪实现

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的视频多目标跟踪实现 …

小魔推行业玩法:生活美容怎么做短视频矩阵?

如今每个实体老板都想让自己生意做的更好&#xff0c;那就需要有更多获取流量的方式&#xff0c;获得大量的同城曝光&#xff1b;在市场内卷的状况下&#xff0c;通过短视频来做门店引流无疑是绝佳的方式&#xff0c;让更多同城的用户知晓自己的门店&#xff0c;这个时候通过小…

HarmonyOS4.0系统性深入开发18公共事件简介

公共事件简介 HarmonyOS通过CES&#xff08;Common Event Service&#xff0c;公共事件服务&#xff09;为应用程序提供订阅、发布、退订公共事件的能力。 公共事件从系统角度可分为&#xff1a;系统公共事件和自定义公共事件。 系统公共事件&#xff1a;CES内部定义的公共事…

对比学习2024最新SOTA&应用方案分享,附14篇必读论文和代码

同学们发现没有&#xff0c;对比学习在我们的日常工作生活中已经很常见了&#xff0c;比如推荐系统任务&#xff0c;为用户推荐相似的商品或预测用户的购买行为&#xff1b;又比如图像检索&#xff0c;为用户找相似图片或识别不同物体。另外还有语音识别、人脸识别、NLP&#x…

43-函数的声明定义,函数表达式定义,函数的调用,声明提升,参数,形参,实参

1.函数声明定义 function 函数名(){} 2.函数表达式定义 匿名式函数表达式 var 函数名 function(){} 命名式函数表达式 var 函数名 function 函数关键字(){} 3.函数的调用 var fn function f(){alert("aaa");}//函数名&#xff08;&#xff09;//函数想调用几次…

京东年度数据报告-2023全年度游戏本十大热门品牌销量(销额)榜单

同笔记本市场类似&#xff0c;2023年度游戏本市场的整体销售也呈下滑态势。根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;京东平台上游戏本的年度销量累计超过350万&#xff0c;同比下滑约6%&#xff1b;销售额将近270亿&#xff0c;同比下滑约11%。 鲸参谋综合了京东…

7、防写一个shell 命令解释器

1、代码部分 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_INPUT_LENGTH 100void parse_command(char *command) {// 用于存储解析后的命令和参数char cmd[MAX_INPUT_LENGTH];char args[MAX_INPUT_LENGTH];// 将输入的命令拷贝到…

Java Swing 图书借阅系统 窗体项目 期末课程设计 窗体设计

视频教程&#xff1a; 【课程设计】图书借阅系统 功能描述&#xff1a; 图书管理系统有三个角色&#xff0c;系统管理员、图书管理员、借阅者&#xff1b; 系统管理员可以添加借阅用户&#xff1b; ​图书管理员可以添加图书&#xff0c;操作图书借阅和归还&#xff1b; 借…

JDK安装与配置教程来啦

1.从Oracle公司官网下载JDK安装文件。 官网地址为&#xff1a; http://www.oracle.com/technetwork/java/javase/downloads/index.html 目前最新版本是JDK21,下面就以JDK21举例。 2.需要登录Oracle账户&#xff0c;没有的注册一下就行了。 3.在确认安装的盘符&#xff08;例…

Exception in thread “main“ java.lang.ArrayIndexOutOfBoundsException(数组创建问题)

数组在Java中使用还是比较多的&#xff0c;通过索引去数组中寻值&#xff0c;也可以通过数组索引去赋值 问题描述&#xff1a; 我们在直接使用未被new的数组时就会出现这种情况&#xff0c; 这边简单创建一个运行类 public class a {public static void main(String[] args)…

基于LVGL编写的windows串口工具: LCOM

LCOM: Serial Port Tools based on LVGL (PC Software) 一直以来我都想用LVGL做一个真正意义上的PC软件&#xff0c;来验证或者表达LVGL出色的特性&#xff0c;现在我用LCOM做到了&#xff01; LCOM 是一个基于LVGL编写的串口工具&#xff0c;界面简洁&#xff0c;功能出色&a…

更快更稳的4K响应鼠标,小手玩家也能用,雷柏VT9PRO mini

雷柏今年推出了不少新品&#xff0c;特别是一系列支持4K回报率的鼠标&#xff0c;凭借敏捷的响应速度&#xff0c;获得了非常好的评价。不过之前雷柏出的4K鼠标都多适合中大手&#xff0c;对小手用户不友好&#xff0c;而且配色较少&#xff0c;都是黑白色的基础款&#xff0c;…

数字集成系统设计——物理设计

目录 一、布局规划 1.1 规划 1.2 I/O单元 1.3 电源网络 1.3.1 要求 1.3.2 网络架构 1.3.3 混合信号芯片示例 1.4 布局 二、时钟分布 2.1 时钟偏斜 2.2 时钟分布网络 2.3 时钟树综合 2.4 时钟树收敛 三、布线与参数提取 3.1 布线(Routing) 3.2 布线规则示例 …
最新文章