注解

1.概念

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

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

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

2.作用

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

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

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

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

3.Java 的三大注解

1.@Override:表明子类中覆盖了超类中的某个方法,如果写错了覆盖形式,编译器会报错

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

3.@suppresswarnings:抑制警告

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

​ 一般传递参数: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(); }
}

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

  1. Java 集合看这一篇就够了

    大家好,这里是<齐姐聊数据结构>系列之大集合. 话不多说,直接上图: Java 集合,也称作容器,主要是由两大接口 (Interface) 派生出来的: Collection 和 Map ...

  2. 想真正了解JAVA设计模式看着一篇就够了。 详解+代码实例

    Java 设计模式   设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结 设计模式分为 23 种经典的模式,根据用途我们又可以分为三大类.分别是创建型模式.结构型模式和行为型模式 列举几种设 ...

  3. Java NIO看这一篇就够了

    原文链接:https://mp.weixin.qq.com/s/c9tkrokcDQR375kiwCeV9w? 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomca ...

  4. 关于Java多线程看这一篇就够了,从创建线程到线程池分析的明明白白

    前言 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,即进程空间或(虚空间).进程不依赖于线程而独立存在,一个进程中可以启动多个线程. 线程是指进程中的一个执行流程,一个进程中可 ...

  5. 【java编程】ServiceLoader使用看这一篇就够了

    转载:https://www.jianshu.com/p/7601ba434ff4 想必大家多多少少听过spi,具体的解释我就不多说了.但是它具体是怎么实现的呢?它的原理是什么呢?下面我就围绕这两个问 ...

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

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

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

    紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...

  8. JVM内存模型你只要看这一篇就够了

    JVM内存模型你只要看这一篇就够了 我是一只孤傲的鱼鹰 让我们不厌其烦的从内存模型开始说起:作为一般人需要了解到的,JVM的内存区域可以被分为:线程栈,堆,静态方法区(实际上还有更多功能的区域,并且这 ...

  9. [转帖]nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件

    nginx学习,看这一篇就够了:下载.安装.使用:正向代理.反向代理.负载均衡.常用命令和配置文件 2019-10-09 15:53:47 冯insist 阅读数 7285 文章标签: nginx学习 ...

随机推荐

  1. linux中用户和用户组的概念以及查看命令

    Linux 是多用户多任务操作系统,换句话说,Linux 系统支持多个用户在同一时间内登陆,不同用户可以执行不同的任务,并且互不影响. 例如,某台 Linux 服务器上有 4 个用户,分别是 root ...

  2. 小码哥哥 FastJson--阿里巴巴公司开源的速度最快的Json和对象转换工具

    转载地址:http://www.oschina.net/code/snippet_228315_35122?_t_t_t=0.4667952097048127 class User{ private ...

  3. 【React.js小书】动手实现 React-redux(五):Provider - 方志

    我们要把 context 相关的代码从所有业务组件中清除出去,现在的代码里面还有一个地方是被污染的.那就是 src/index.js 里面的 Index: 1234567891011121314151 ...

  4. chap1-HttpRequest测试类

    # HttpRequest测试类, 封装请求方法 import requests class HttpRequest: def http_request(self, url, method, data ...

  5. OpenResty+缓存穿透基本介绍

    OpenResty                1.lua表达式                 2.Nginx的安装                3.OpenResty              ...

  6. php 正则获取html任意标签

    <?php $temp = ' <div class="num">1</div> <div class="num">2 ...

  7. cesium入门示例-3dTiles加载

    数据转换工具采用cesiumlab1.5.17版本,转换后的3dTiles加载显示比较简单,通过Cesium.Cesium3DTileset接口指定url即可,3dTiles文件可与js前端代码放置一 ...

  8. Archlinux系统运维

    本文将针对Archlinux下的系统运维进行介绍. 内核相关 查看当前内核版本 123 uname -r------------------------------------------------ ...

  9. 吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图(续二)

    #----------------------------------------------------------# # R in Action (2nd ed): Chapter 19 # # ...

  10. JS做深度学习2——导入训练模型

    JS做深度学习2--导入训练模型 改进项目 前段时间,我做了个RNN预测金融数据的毕业设计(华尔街),当时TensorFlow.js还没有发布,我不得已使用了keras对数据进行了训练,并且拟合好了不 ...