Java复习第12天---12.4---基础加强---注解
目录
内容
1、概述
注解与注释的区别。
-
注解:说明程序的,给计算机看的
-
注释:用文字描述程序的,给程序员看的
-
定义:注解(Annotation),也叫元数据,一种代码级别的说明。它是JDk1.5及之后版本引入的特殊。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释。
-
作用分类:
- 编写文档:通过代码里面标识的注解生成文档(生成doc文档)
- 代码分析:通过代码里标识的注解对代码进行分析(通过反射)
- 便宜检查:通过代码里标识的注解让编译器能实现基本的编译检查(Override)
1.1、Javadoc文档
-
示例1.1-1:
package annotation; /** * 注解Javadoc演示 * @author gaogzhen * @since 1.5 * @version 1.0 */ public class TestAnnotationDoc { /** * 计算2个整数相加 * @param a 整数 * @param b 整数 * @return 整数-2数相加的和 */ public int add(int a, int b) { return a + b; } } :通过javadoc命令生成javadoc文档
2、JDK内置注解
-
@Override:检测被该注解标注的方法是否继承自父类(接口)
-
@Deprecated:被该注解标注的方法,表示已经过时,有其他更好的替代方法
-
@SuppressWarnings:表示在注释元素(以及注释元素中包含的所有程序元素)中应该抑制命名的编译器警告
-
示例2-1:
package annotation; public class TestAnno1 { @Override public String toString() { return "TestAnno1 [toString()=" + super.toString() + "]"; } @Deprecated public void method1() {} @MyAnno public void method2() { method1(); } }
3、自定义注解
在自定义注解前看下内置注解的源码:
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* A program element annotated @Deprecated is one that programmers
* are discouraged from using, typically because it is dangerous,
* or because a better alternative exists. Compilers warn when a
* deprecated program element is used or overridden in non-deprecated code.
*
* @author Neal Gafter
* @since 1.5
* @jls 9.6.3.6 @Deprecated
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
由内置注解的源码,看出:
-
格式
元注解 public @interface 注解名{ 属性列表; }
javap命令查看注解
- 本质:注解本质上是接口,默认继承自Annotation
- public interface MyAnno extends java.lang.annotation.Annotation
3.1、注解属性
-
属性:接口中定义的成员方法,即抽象方法
-
要求:
- 属性的返回值类型
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
- 定义了属性,在使用时需要给属性赋值
- 可以给属性设置默认值
- 如果只有1个属性需要赋值,且属性名为value,则使用时可以省略属性名,直接写值即可
- 属性的返回值类型
-
示例3.1-1:
package annotation; public @interface MyAnno { int show1(); String name() default "gaozhen"; }
3.2、元注解
用于描述注解的注解。常用元注解:
-
@Target:描述注解可以作用的位置
- ElementType取值
- TYPE:可以作用于类上
- METHOD:可以作用于方法上
- FIELD:可以作用于属性上
- ElementType取值
-
@Retention:描述注解被保留的阶段
- @Retention(RententionPolicy.Runtime):被描述的注解会保留到class字节码中,并被JVM读取
-
@Documented:描述注解是否被抽取到API文档
-
@Inherited:描述注解是否被继承到子类
3.3、解析注解
-
示例3.3-1:用注解实现执行任意对象的任意方法
package annotation; 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 Pro { String className(); String methodName(); } package annotation; public class AnnoDemo1 { public void show() { System.out.println("Anno Demo1"); } } package annotation; import java.lang.reflect.Method; /** * 通过注解实现任意对象任意方法的执行 * @author Administrator * */ @Pro(className="annotation.AnnoDemo1", methodName="show") public class TestReflect1 { public static void main(String[] args) throws Exception { // 1、获取类对象 Class<TestReflect1> cls = TestReflect1.class; // 2、获取注解对象 Pro anno = cls.getAnnotation(Pro.class); // 3、获取注解属性 String className = anno.className(); String methodName = anno.methodName(); // 4、反射生成对象执行方法 Class<?> c = Class.forName(className); Object obj = c.newInstance(); Method method = c.getDeclaredMethod(methodName, null); method.invoke(obj, null); } } 测试结果: Anno Demo1
4、小案例
-
定义一个计算器类,设计个简单的测试框架,并记录日志
-
检测注解@check代码4-1:
package reflect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Check { }
-
计算器类代码4-2:
package reflect; public class Calculator { // 加法 @Check public void add() { 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..."); } }
-
测试类框架4-3:
package reflect; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Method; public class TestCalculator { public static void main(String[] args) throws IOException { // 1、定义计算器对象 Calculator c = new Calculator(); // 2、获取字节码对象 Class<Calculator> cls = (Class<Calculator>) c.getClass(); // 3、获取所有方法 Method[] methods = cls.getMethods(); // 6、捕获异常 int count = 0; // 记录异常次数 BufferedWriter bw = new BufferedWriter(new FileWriter("calculator.log")); for(Method method: methods) { // 4、获取@check注解的方法 if(method.isAnnotationPresent(Check.class)) { // 5、执行@注解的方法 // 6、捕获异常 try { method.invoke(c, null); } catch (Exception e) { // 7、记录日志 count++; 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("本次测试一共出现 " + count + " 次异常"); bw.flush(); bw.close(); } } 测试结果:calculator.log内容 div方法出现异常 异常的名称:ArithmeticException 异常的原因:/ by zero ============ 本次测试一共出现 1 次异常
后记 :
本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785
前端项目源代码地址:https://gitee.com/gaogzhen/vue-leyou
后端JAVA源代码地址:https://gitee.com/gaogzhen/JAVA