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

【详解 Java 注解】

前言:

注解(Annotation)是Java中的一种特殊符号,用来为代码提供额外的信息。它不会改变程序的逻辑,只是用来给编译器或工具提供指示。例如,@Override 表示一个方法是重写了父类的方法,@Deprecated 标记一个方法已经不建议使用。本文先讲一些简单的注解,主要带大家了解一下什么是注解,还有它的一些基本使用示例,元注解等等后续更高级的注解会在框架慢慢讲解。

引入

【1】历史:
JDK5.0 新增 ---  注解(Annotation),也叫元数据

【2】什么是注解?

注解其实就是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用注解,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。

使用注解时要在其前面增加@符号,并把该注解当成一个修饰符使用。用于修饰它支持的程序元素。

【3】注解的重要性:

Annotation 可以像修饰符一样被使用,可用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotation的"name=value"对中。在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/ArIdroid中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置等。未来的开发模式都是基于注解的,JPA(java的持久化API)是基于注解的,Spring2.5以. E都是基于注解的,Hibernate3.x以后也是基于注解的,Struts2有一部分也是基于注解的了,注解是一种趋势,一定程度上可以说 :框架=注解+反射+设计模式

注解的使用实例

JUnit注解

@Test
@Before
@After 

具体详细可以参考之前写的JUnit文章。

文档相关的注解

说明注释允许你在程序中嵌入关于程序的信息。你可以使用 javadoc 工具软件来生成信息,并输出到HTML文件中。
说明注释,使你更加方便的记录你的程序信息。
文档注解我们一般使用在文档注释中,配合javadoc工具
javadoc 工具软件识别以下标签:


 其中注意:

Ø @param @return和@exception这三个标记都是只用于方法的。

Ø @param的格式要求: @param 形参名 形参类型 形参说明

Ø @return的格式要求: @return 返回值类型返回值说明,如果方法的返回值类型是void就不能写

Ø @exception的格式要求: @exception 异常类型异常说明

Ø @param和@exception可以并列多个

代码:

/**
 * @author  : themyth
 * @version : 1.0
 */
public class Person {
    /**
     * 下面是eat方法,实现了xxx功能。
     * @param num1 就餐人数
     * @param num2 点了几个菜
     */
    public void eat(int num1,int num2){
    }
    /**
     *
     * @param age 年龄
     * @return int
     * @exception RuntimeException 当年龄过大的时候
     * @exception IndexOutOfBoundsException 当年龄过小的时候
     * @see Student
     */
    public int sleep(int age){
        new Student();
        if(age>100){
            throw new RuntimeException();
        }
        if(age<0){
            throw new IndexOutOfBoundsException();
        }
        return 10;
    }
}

IDEA中的javadoc使用:

 

防止乱码:

JDK内置的3个注解

@Override:限定重写父类方法,该注解只能用于方法

/**
 * @auther: themyth
 */
public class Person {
    public void eat(){
        System.out.println("父类eat");
    }
}
/**
 * @auther: themyth
 */
public class Student extends Person{
    /*
    @Override的作用:限定重写的方法,只要重写方法有问题,就有错误提示。
     */
    @Override
    public void eat(){
        System.out.println("子类eat");
    }
}

 @Deprecated:用于表示所修饰的元素(类,方法,构造器,属性等)已过时。通常是因为所修饰的结构危险或存在更好的选择

/**
 * @auther: themyth
 */
public class Student extends Person{
    /*
    @Override的作用:限定重写的方法,只要重写方法有问题,就有错误提示。
     */
    @Override
    public void eat(){
        System.out.println("子类eat");
    }
    /*
    在方法前加入@Deprecated,这个方法就会变成一个废弃方法/过期方法/过时方法
     */
    @Deprecated
    public void study(){
        System.out.println("学习");
    }
}

 

@SuppressWarnings:抑制编译器警告

import java.util.ArrayList;
/**
 * @auther: themyth
 */
public class Test02 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        @SuppressWarnings("unused")
        int age = 10;
        int num =10;
        System.out.println(num);
        @SuppressWarnings({"unused","rwatypes"})
        //第一个参数:抑制变量没有被使用的警告,第二个参数:抑制推荐使用泛型的警告
        ArrayList a1 = new ArrayList();
    }
}

上述age变量没有被使用,ArrayList没有用泛型表示。 

实现替代配置文件功能的注解

在servlet3.0之前的配置:

package com.bjsxt.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

   
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service方法被调用了...");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置Servlet-->
    <!--配置Servlet的信息-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.bjsxt.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--配置Servlet的映射路径-->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <!--http://localhost:8080/01-hello-servlet/hello-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

自定义注解

【1】自定义注解使用很少,一般情况下都是用现成的注解
【2】如何自定义注解:

发现定义的注解的声明使用的关键字:@interface,跟接口没有一点关系
【3】注解的内部:
以@SuppressWarnings为例,发现内部:


这value是属性还是方法?
答案:看上去是无参数方法,实际上理解为一个成员变量,一个属性  ---函数式属性(方法式属性)
无参数方法名字--》成员变量的名字
无参数方法的返回值--》成员变量的类型
这个参数叫 配置参数

无参数方法的类型:基本数据类型(八种),String,枚举,注解类型,还可以是以上类型对应的数组。

PS:如果只有一个成员变量的话,名字尽量叫value。

【4】使用注解:

(1)使用注解的话,如果你定义了配置参数,就必须给配置参数进行赋值操作: 

@MyAnnotation(value={"abc","def","hij"})
public class Person {
}

(2)如果只有一个参数,并且这个参数的名字为value的话,那么value=可以省略不写

@MyAnnotation({"abc","def","hij"})
public class Person {
}

(3)如果你给配置参数设置默认的值了,那么使用的时候可以无需传值:

public @interface MyAnnotation2 {
    String value() default "abc";
}

使用:

@MyAnnotation2
@MyAnnotation({"abc","def","hij"})
public class Person {
}

(4)一个注解的内部是可以不定义配置参数的:

public @interface MyAnnotation3 {
}

内部没有定义配置参数的注解--》可以叫做标记

内部定义配置参数的注解--》元数据


【5】注解的使用:

现在只学习注解的大致技能点,具体怎么应用  后面慢慢学习。 

元注解 

元注解是用于修饰其它注解的注解。 

举例:

JDK5.0提供了四种元注解:Retention, Target, Documented, Inherited

@Retention

用于修饰注解,用于指定修饰的那个注解的生命周期,@Rentention包含一个RetentionPolicy枚举类型的成员变量,使用@Rentention时必须为该value成员变量指定值:

➢RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释,在.class文件中不会保留注解信息

案例:

反编译查看字节码文件:发现字节码文件中没有MyAnnotation这个注解:

➢RetentionPolicy.CLASS:在class文件中有效(即class保留),保留在.class文件中,但是当运行Java程序时,他就不会继续加载了,不会保留在内存中,JVM不会保留注解。如果注解没有加Retention元注解,那么相当于默认的注解就是这种状态

案例:

反编译看字节码文件,字节码文件中带有MyAnnotation注解:

➢RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行 Java程序时,JVM会保留注释,加载在内存中了,那么程序可以通过反射获取该注释

@Target

用于修饰注解的注解,用于指定被修饰的注解能用于修饰哪些程序元素

@Target也包含一个名为value的成员变量。

案例

import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE,CONSTRUCTOR,METHOD})//类 构造器 方法
public @interface MyAnnotation4 {
}

使用:

因为此时Target里面没有传入FIELD参数,所以MyAnnotation4不能修饰属性

@Documented(很少)

用于指定被该元注解修饰的注解类将被javadoc工具提取成文档默认情况下,javadoc是 不包括注解的,但是加上了这个注解生成的文档中就会带着注解了

案例:如果:Documented注解修饰了Deprecated注解,

那么Deprecated注解就会在javadoc提取的时候,提取到API中:

@Inherited(极少)

被它修饰的Annotation将具有继承性。如果某个类使用了被

@Inherited修饰的Annotation,则其子类将自动具有该注解。

案例:

注解:如果MyAnno注解使用了@Inherited之后,就具备了继承性,那么相当于子类Student也使用了这个MyAnno


http://www.kler.cn/news/295014.html

相关文章:

  • 一些数学经验总结——关于将原一元二次函数增加一些限制条件后最优结果的对比(主要针对公平关切相关的建模)
  • 分数阶微积分MATLAB计算
  • 将你的github仓库设置为web代理
  • Java零基础-如何在分布式系统中进行日志管理?
  • 【鸿蒙】HarmonyOS NEXT星河入门到实战1-开发环境准备
  • Vulnhub:Dr4g0n b4ll 1
  • Qt/C++开源项目 TCP客户端调试助手(源码分享+发布链接下载)
  • <class ‘pyspark.sql.dataframe.DataFrame‘>
  • Eureka原理与实践:构建高可用微服务架构的基石
  • MCU5.51单片机的最小系统
  • IDEA git提交时如何忽略某个文件或文件夹
  • 任务执行拓扑排序(华为od机考题)
  • Elasticsearch - SpringBoot 索引与文档相关demo
  • Spring Boot 部署方案!打包 + Shell 脚本详解
  • 【知识分享】MQTT实战-使用mosquitto客户端连接emqx服务器
  • 【人工智能】Transformers之Pipeline(十五):总结(summarization)
  • ubuntu上通过openvswitch卸载实现roce over vxlan
  • 橘子学ES实战操作之管道类型Ingest pipelines的基本使用
  • Kubernetes 1.25 containerd 环境部署 SuperMap iManager
  • 【MRI基础】TR 和 TE 时间概念
  • 文心快码前端工程师观点分享:人机协同新模式的探索之路(三)
  • day44-测试平台搭建之前端vue学习-基础4
  • java-redis-雪崩
  • QString如何格式化字符串
  • 3.门锁_STM32_矩阵按键设备实现
  • 手机同时传输USB功能与充电的实现及LDR6500的作用
  • Java爬虫开发:Jsoup库在图片URL提取中的实战应用
  • 使用Node-API进行线程安全开发
  • 枚举和联合体
  • 在生产线打包机中RFID技术的赋能