Java注解 看这一篇就够了

注解

1.概念

注解:说明程序的。给计算机看的

注释:用文字描述程序的。给程序员看的

注解的定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

2.作用

①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】:

? shift+右键 -> 在此处打开Powershell窗口 -> 输入:javadoc .\类名.java

②代码分析:通过代码里标识的注解对代码进行分析【使用反射】

③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

3.Java 的三大注解

[email protected]:表明子类中覆盖了超类中的某个方法,如果写错了覆盖形式,编译器会报错

[email protected]:废弃的(过时的)表明不希望别人在以后使用这个类,方法,变量等.

[email protected]:抑制警告

? 达到抑制编译器产生警告的目的,但是不很不建议使用,因为后期编码人员看不懂编译器 提示的警告,不能更好的选择更好的类去完成任务。

? 一般传递参数:all @SuppressWarnings("all") 可以加在类的上面一行,这样代码就 没有警告了,显得比较干净。

4.自定义注解:

本质:注解本质上就是一个接口,该接口默认继承Annotation接口

? public interface MyAnno extends java.lang.annotation.Annotation {}

? 可以在Powershell窗口反编译看看:

格式:

public @interface 注解名称{
/* 属性列表;
 * 注解中的属性 主要定义抽象方法 不定义常量
 * 抽象方法的返回值类型有要求():
 *      1.基本数据类型
 *      2.String
 *      3.枚举类型
 *      4.注解
 *      5.数组(以上几种类型的数组)
 */
}
//属性列表中抽象方法的举例:
public @interface MyAnno {

     int getName();

     String getStr();

     Season getSeason();   //新建Enum枚举类Season

     MyAnno2 getMyAnno2();  //新建Annotation注解类MyAnno2

    String[] value();

    //int getName() default 0;  //如果不想为注解中的某个属性赋值,可以为其定义默认值

}
//枚举类
public enum Season {
    SPRING,SUMMER,AUTUMN,WINtER
}

注解类定义了属性,那么在使用时必须给属性赋值。

/*
1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。int getName() default 0;
    @MyAnno()
    public static void  test02() {}
2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。

3. 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略。
*/
//对我们自定义的MyAnno注解类的使用:
@MyAnno(getName = 1, getStr = "100", getSeason = Season.SPRING, getMyAnno2= @MyAnno2,value = {"1","2"})
public static void  test01() {}

元注解:用于描述注解的注解(注解前面的注解)

@Target:描述注解能够作用的位置
    ElementType取值:
        TYPE:可以作用于类上
         FIELD:可以作用于成员变量上
        METHOD:可以作用于方法上
@Retention:描述注解被保留的阶段
    SOURCE: 源代码阶段, 被编译器忽略
    CLASS:  注解将会被保留在Class文件中,但在运行时并不会被VM保留。这是默认行为,所有没           有用Retention注解的注解,都会采用这种策略。
    RUNTIME:保留至运行时。所以我们可以通过反射去获取注解信息。
    @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
//下面两个了解
@Documented:描述注解是否被抽取到api文档中
@Inherited:描述注解是否被子类继承

对Java的三大注解之一的SuppressWarnings注解进行分析:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();      //只有一个属性,且名称为value,且为数组赋值
}
@SuppressWarnings(value={"all"})
public class AnnoTest {}
//同样可以这么使用
@SuppressWarnings({"all"})  //使用时可以省略value
@SuppressWarnings("all")    //使用时可以省略{}

5.注解的使用

注解的作用:将我们为注解中的属性(抽象方法)赋的值提取出来,在类中使用

  1. 获取注解定义的位置的对象 (Class,Field,Method)
  2. 获取指定的注解:

    getAnnotation(Class annotationClass):方法返回该元素的指定类型的注释,如果是这样的注释,否则返回null

    ? 参数:annotationClass -- 对应于注释类型的Class对象。

6.案例

1.定义该类使用注解加反射,实现不修改任何代码(只需要修改注解中的值),就可以实现调用任意类中的任意方法

//自定义注解类
@Retention(RUNTIME)
@Target(TYPE)
public @interface Pro {

    String className();   //通过该属性获取到类名
    String methodName();   //通过该属性获取到方法名

}
@SuppressWarnings("all")
@Pro(className = "com.huike.b.useanno.Demo2", methodName = "show")
public class AnnoTest {

    public static void main(String[] args) throws Exception {

        //1.解析注解
        //1.1:获取加注解的类的字节码文件对象
        //1.2:获取注解对象
        Class cls = AnnoTest.class;

        //通过当前类的Class对象获取到类上的注解对象
        Pro pro = (Pro) cls.getAnnotation(Pro.class);

        //2.调用注解中的抽象方法  获取到返回值
        String className = pro.className();
        String methodName = pro.methodName();

        //3.获取到返回值所对应的类的Class对象
        Class cls1 = Class.forName(className);  

        //4.创建该类的对象
        Object object = cls1.newInstance();

        //5.获取到该类的特定方法对象
        Method method = cls1.getMethod(methodName);

        //6.执行方法
        method.invoke(object);

    }
}

2.测试框架:

  •  当main方法执行后,会自动执行被检测的所有方法(被加了Check注解的方法),判断方法内是否有异常
  •  如果没有就算了,如果有异常,会自动记录到特定的文件中,文件中记录哪些方法出异常了,异常的名称是什么异常的原因是什么   
  •  得出总结:本次共测试了多少方法,出现了多少次异常
//Check注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
//自定义Calculator类,被用于测试
public class Calculator {

    //加法
    @Check
    public void add() {
        String str = null;
        str.toString();
        System.out.println("1 + 0="+(1 + 0));
    }

    //减法
    @Check
    public void sub() {
        System.out.println("1 - 0="+(1 - 0));
    }

    //乘法
    @Check
    public void mul() {
        System.out.println("1 * 0="+(1 * 0));
    }

    //除法
    @Check
    public void div() {
        System.out.println("1 / 0="+(1 / 0));
    }

    public void show() {
        System.out.println("永无bug...");
    }

}
//测试类
public class CheckDemo {

    public static void main(String[] args) throws Exception{

        //1.创建计算器对象 得到对应的Class对象
        Calculator c = new Calculator();
        Class cls = c.getClass();
        //2.获取到该对象中的所有的方法
        Method[] methods = cls.getDeclaredMethods();

        int num01 = 0;  //定义一个int类型的值用于记录出现的异常次数
        int num02 = 0;  //定义一个int类型的值用于记录带有Check注解的方法数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        //3.判断哪些方法上有Check注解
        for (Method method : methods) {

            //该方法用于判断 方法上是否有特定的注解
            //4.如果有Check注解,执行该方法 如果该方法无任何异常,就算了
            if (method.isAnnotationPresent(Check.class)) {
                num02++;
                try {
                    method.invoke(c);   //如果有注解,则执行该方法
                } catch (Exception e) {
                    num01++;
                    //5.如果有异常,记录异常信息,并通过IO流打印到文件中
                    //如果方法存在异常 需要在此通过IO流捕获
                    bw.write(method.getName()+" 方法出异常了...");
                    bw.newLine();
                    //获取到异常的简短名称
                    bw.write("异常的名称为:"+ e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因是:"+ e.getCause().getMessage());
                    bw.newLine();
                    bw.write("------------------------------------------------");
                    bw.newLine();
                }

            }
        }

        bw.write("本次测试结束了,一共测试了"+num02+"个方法,共出现了"+num01+"次异常!");
        bw.flush();
        bw.close();

    }
}

原文地址:https://www.cnblogs.com/yZzcXQ/p/JavaSE-anno.html

时间: 2024-10-07 08:28:52

Java注解 看这一篇就够了的相关文章

Java NIO看这一篇就够了

原文链接:https://mp.weixin.qq.com/s/c9tkrokcDQR375kiwCeV9w? 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty.学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能.在前篇文章<NIO基础>中我们学习了NIO的相关理论知识,而在本篇中我们一起来学习一下Java NIO的实战知识. 一.概述 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Se

Java中的多线程你只要看这一篇就够了

Java中的多线程你只要看这一篇就够了 引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应"多角色"的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的"生产者,消费者模型". 很多人都对其中的一些概念不够明确,如同步.并发等等,让我

Java中的多线程=你只要看这一篇就够了

如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”. 很多人都对其中的一些概念不够明确,如同步.并发等等,让我们先建立一个数据字典,以免产生误会. 多线程:指的是这个程序(一个进程)运

关于 Docker 镜像的操作,看完这篇就够啦 !(下)

原文:关于 Docker 镜像的操作,看完这篇就够啦 !(下) 紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌握的.本文将带您一步一步,图文并重,上手操作来学习它. 目录: 一.Docker 删除镜像 1.1 通过标签删除镜像 1.2 通过 ID 删除镜像 1.3 删除镜像的限制 1.4 清理镜像 二.Docker 创建镜像 2.1 基于已有的镜像创建

用markdown写博客,看这一篇就够了,附markdown文件分享

0. 前言 为什么用markdown写博客? 在写博客的过程中,最大的"痛点"在于写作中总是被"格式"之类的困扰,无法专注于内容写作: 在线写博客,会被网络或者编辑器本身所拖累: 本文介绍的markdown写作,可以使你专注于博客内容本身,写好即成稿: 更重要的是,博客内容及相关素材保存在本地,可以几乎不用修改就可以发布在不同的平台,类似java程序的"一次编写,到处运行". 记得上次用markdown写博客,尽管我有markdown使用经验,但

iOS动画详解(学习动画看这一篇就够了)

iOS动画详解(学习动画看这一篇就够了) 一.基础知识 CAAnimation.png 二.CABasicAnimation 1. 动画的属性和解释 2.属性值的解释 repeatCount : 如果在swift中需要一直不断重复:Float.infinity,OC:HUGE_VALF timingFunction: timingFunction.png kCAMediaTimingFunctionLinear--在整个动画时间内动画都是以一个相同的速度来改变.也就是匀速运动.一个线性的计时函数

[转]关于深度学习,看这一篇就够了

关于深度学习,看这一篇就够了 原文地址:http://www.dlworld.cn/XueXiSuanFa/13.html [日期:2016-04-26] 来源:36氪  作者: [字体:大 中 小] 编者按:本文作者王川,投资人,中科大少年班校友,现居加州硅谷,个人微信号9935070,36 氪经授权转载自其个人微信公众号 investguru. 一 2016 年一月底,人工智能的研究领域,发生了两件大事. 先是一月二十四号,MIT 的教授,人工智能研究的先驱者,Marvin Minsky 去

中后台产品的表格设计,看这一篇就够了(原型规范下载)

中后台产品的表格设计,看这一篇就够了(原型规范下载) 2018年4月16日luodonggan 中后台产品的表格设计,看这一篇就够了(原型规范下载) 经过了将近一年的后台产品经历,踩了很多坑,试了很多错,也学习到了很多东西,目前也形成了自己的一套规范.本文将其中的部分收获汇总成文,希望能够对大家有所帮助. 后台产品有一个很重要.常见的元素,就是表格.表格承担着详情入口.数据展示的功能,看似简单,其实里面的细节特别多.在以效率为最重要的需求的后台产品中,如何设计一个能够高效率地进行查看和编辑的表格

源码时代前端干货分享| AE如何实现文字消散效果?看这一篇就够了!

源码时代前端干货分享| AE如何实现文字消散效果?看这一篇就够了!首先:1.新建合成IMAge012.新建一个纯色层做背景(如果自带背景可以忽略)02 3.新建文本图层034.打上文字,调整文字大小,让文字在画布中居中04 然后:5.给文字添加一个蒙版05 6.在0秒的位置的蒙版路径打上关键帧067.0秒的时候蒙版路径最大,3秒的时候蒙版路径最小078.继续添加蒙版羽化089.再新建一个合成为置换0910.新建一个纯色的白图层1011.给它添加一个蒙版1112.在蒙版路径上打上关键帧13.0秒的