iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java中注解、元注解怎么用
  • 488
分享到

Java中注解、元注解怎么用

2023-06-29 00:06:46 488人浏览 泡泡鱼
摘要

这篇“Java中注解、元注解怎么用”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“Java中注解、元注解怎么用”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望大家通过这篇文章有所收获,下面让我们

这篇“Java中注解、元注解怎么用”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“Java中注解、元注解怎么用”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望大家通过这篇文章有所收获,下面让我们一起来看看具体内容吧。

注解

Java注解也称Java标注,是jdk1.5(5.0)后的新特征。Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java注解可以通过反射获取标注内容,在编译器生成类文件时,标注可以被嵌入到字节码中,Java虚拟机可以保留标注内容,在运行时可以获取到标注内容,当然它也支持自定义Java标注

功能:用于说明程序

用途:一般用在框架中使用

格式:@AnnotationName

文档注释:

@param @return @Exception从根本上是一个注释,不存在代码编译,不会生成对应的文档

注解:

@Override并不是没有编译就有效果,是因为不管是Eclipse还是idea都可以预编译Java代码生成对应的.class文件的

注解作用

生成文档

代码中生成对应的JavaDoc api文档

@param @return

【IDEA JavaDoc工具使用参数】

Other Command Line Arguments:-encoding utf-8 -charset utf-8

解决中文乱码,因为IDEA默认编码集为UTF-8 windows默认编码集为 GBK

代码检查

继承重写,或者说接口遵从之后的实现中,存在@Override

代码数据获取:【小型框架】

通过反射获取指定注解中的一些内容,例如:配置,数据,操作,验证等

Java预定义的注解

@Override

重写/实现方法的情况下,检查方法声明是否和父类或者接口中的方法声明一致,强制格式检查

@Deprecated

标记当前方法已过时

@SuppressWarnings(“all”)

压制警告,可以用于一些代码中存在明确无异常的情况下,压制一些警告

Annotation注解属性【难点】

属性

开发实际使用注解的方式中,数据使用方式更加偏向于属性概念

使用

  1. 书写代码中使用
    @MyAnnotation(id=1, name=“ocean”, age=16)

  2. 使用反射时,会涉及到getXXX方法
    通过属性名获取对应值的概念来完成的

实际上是利用abstract方法来完成属性概念的

属性使用的格式【实际按照方法格式操作】

  1. 属性的值数据类型和对应的具体数据 => 返回值类型和返回的数据属性类型支持:

    1. 基本数据类型

    2. String类型

    3. 其他数据类型

    4. enmu枚举类型,一个带有名字的常量,为了更好的阅读性和操作

    5. 以上类型对应的数组

  2. 属性值要求

    1. 如果属性是数组类型, {}大括号保存,并且不同的内容,使用,隔开属性的键名字 ==> 方法的名字

    2. 定义属性时可以使用default关键字,加上默认值,该属性在使用的过程中是没有强制要求属性值,如果没有赋予属性值,采用对应的默认值操作,如果赋值,使用对应值

    3. 如果注解中有且只有一个value属性,或者说注解中除value属性之外,都有默认值,不管是类,方法,成员变量,包使用当前注解是可以直接在括号内加入
      对应数据类型数值

Java中注解、元注解怎么用

自定义注解

格式:public @interface AnnotationName {属性列表;}Annotation注解是可以编译得到对应的.class字节码文件,验证了注解是可以参与编译过程的通过反编译工具可以得到一下内容【Annotation本质】public interface MyAnnotation1 extends java.lang.annotation.Annotation {}MyAnnotation1本质是一个interface,同时java.lang.annotation.Annotation 子接口
package cn.ocean888.a_annotation.MyAnnotation;public @interface MyAnnotation1 {    // 属性 ==> 方法形式}

元注解

基于注解的解释,用来约束注解的的一些操作问题

@Retention

表示这个注解的保存方式,是只在代码中,还是编入class文件中,或者是运行时可以通过反射访问

RetentionPolicy.RUNTIME:当前注解会编译生成对应的.class字节码文件,并且可以加载到JVM中,参与代码执行

RetentionPolicy.CLASS

RetentionPolicy.SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)

@Document

标记这些注解是否包含在用户文档中

是否可以通过JavaDoc工具,生成对应的API文档

@Target

标记这个注解应该是那种Java成员

属性:ElementType

TYPE:当前注解可以用于类声明

METHOD:当前注解可以用于方法声明位置

FIELD:当前注解可以用于成员变量声明位置

@Inherited

标记这个注解是继承于那个注解类(默认 注解不继承于任何子类)

获取类上的注解

Java获取类上的注解有下面3个方法:

  • Class.getAnnotations() 获取所有的注解,包括自己声明的以及继承的

  • Class.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的

  • Class.getDeclaredAnnotations() 获取自己声明的注解、

java.lang.Class类的isAnnotation()方法用于检查此Class是否为Annotation类型

java.lang.Class类的isAnnotationPresent()方法用于检查此类中是否存在指定注释类型的注释

实例:

实例1:两种属性文件的加载的方式

Java中注解、元注解怎么用

properties

className = cn.ocean888.a_annotation.Personid = 1name = "ocean"

Person类

package cn.ocean888.a_annotation;public class Person {    Integer id;    String name;    public Person() {    }    public Person(Integer id, String name) {        this.id = id;        this.name = name;    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "Person{" +                "id=" + id +                ", name='" + name + '\'' +                '}';    }}

第一种使用反射来完成

package cn.ocean888.a_annotation;import java.io.FileInputStream;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.Properties;public class Demo1 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, NoSuchFieldException {        Properties properties = new Properties();        properties.load(new FileInputStream("./src/1.properties"));        String className = properties.getProperty("className");        String id = properties.getProperty("id");        String name = properties.getProperty("name");        System.out.println(className);                Class<?> aClass = Class.forName(className);        Person person = (Person) aClass.getConstructor().newInstance();        System.out.println(person);        Field declaredField = aClass.getDeclaredField("id");        declaredField.setAccessible(true);        declaredField.set(person, Integer.parseInt(id));        Field declaredField2 = aClass.getDeclaredField("name");        declaredField2.setAccessible(true);        declaredField2.set(person, name);        System.out.println(person);    }}

Java中注解、元注解怎么用

第二种使用反射加注解的方式来完成

自定义注解

package cn.ocean888.a_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)@interface MyAnnotaion1 {    // 属性    String className();    int id();    String name();}

ReflectAnnotation.java

package cn.ocean888.a_annotation;import java.lang.annotation.Annotation;@MyAnnotaion1(className = "cn.ocean888.a_annotation.Person",    id = 2,    name = "ocean")public class ReflectAnnotation {    public static void main(String[] args) {        // 加载ReflectAnnotation        Class<ReflectAnnotation> cls = ReflectAnnotation.class;        // 因为注解再类名之上,通过Class获取对应的Annotation        MyAnnotaion1 annotation = cls.getAnnotation(MyAnnotaion1.class);        String s = annotation.className();        int id = annotation.id();        String name = annotation.name();        System.out.println(s);        System.out.println(id);        System.out.println(name);    }}

Java中注解、元注解怎么用

实例2使用注解测试代码运行

对Tools方法中带有@Check注解标记的方法进行检查

Java中注解、元注解怎么用

Tools.java

package cn.ocean888.a_annotation_checkMethod;import java.util.ArrayList;public class Tools {    @Check    public void test1() {        String str = null;        System.out.println(str.toString());    }    @Check    public void test2() {        int[] arr = null;        System.out.println(arr[5]);    }    @Check    public void test3() {        int[] arr = {1,2,3,4,5};        System.out.println(arr[3]);    }    @Check    public void test4() {        ArrayList<Integer> integers = new ArrayList<>();        System.out.println(integers.get(20).toString());    }    @Check    public void test5() {        throw new NullPointerException("NullPointException");    }}

Utils.java

package cn.ocean888.a_annotation_checkMethod;public class Utils {    @Check    public void test() {        throw new IndexOutOfBoundsException("下标越界");    }}

Check.java

package cn.ocean888.a_annotation_checkMethod;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Check {}

ClassAnnotation.java

package cn.ocean888.a_annotation_checkMethod;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.TYPE)public @interface ClassAnnotation {    String className();}

TestProject.java

package cn.ocean888.a_annotation_checkMethod;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;@ClassAnnotation(className = "cn.ocean888.a_annotation_checkMethod.Tools")public class TestProject {    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {        // 从注解中获取对应的属性        Class<TestProject> testProjectClass = TestProject.class;        // 获取所有指定的注解        ClassAnnotation annotation = testProjectClass.getAnnotation(ClassAnnotation.class);        String s = annotation.className();        // s = cn.ocean888.a_annotation_checkMethod.Utils        Class<?> aClass = Class.forName(s);        Object tools = aClass.getConstructor().newInstance();        // 获取所有Tools类内的方法,不包括父类方法        Method[] declaredMethods = aClass.getDeclaredMethods();        // 记录错误出现次数        int count = 0;        long l = System.currentTimeMillis();        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("./src/log.txt"));        // 遍历方法数组        for (Method declaredMethod : declaredMethods) {            declaredMethod.setAccessible(true);            // 判断当前方法是否带有注解@Check标记            if (declaredMethod.isAnnotationPresent(Check.class)) {                try {                    declaredMethod.invoke(tools);                } catch (Exception e) {                    count += 1;                    // 1.哪一个方法出现异常                    bufferedWriter.write("方法:" + declaredMethod.getName());                    bufferedWriter.newLine();                    // 2.发生异常原因,获取对应的类型                    bufferedWriter.write("异常类型:" + e.getCause().getClass().getSimpleName());                    bufferedWriter.newLine();                    // 3.异常信息                    bufferedWriter.write("异常信息:" + e.getCause().getMessage());                    bufferedWriter.newLine();                }            }        }        long l1 = System.currentTimeMillis();        bufferedWriter.write("出现错误的次数" + count);        bufferedWriter.newLine();        bufferedWriter.write("总耗时" + (l1 - l));        bufferedWriter.close();    }}

代码的灵活性在于可以对className直接进行替换

Java中注解、元注解怎么用

Java中注解、元注解怎么用

注解使用总结

  • 注解在大多数情况下,都是使用过程,而不是自定义,会使用到框架中预处理好的注解

  • 注解使用对象

    • 编译器

    • 解析代码

    • JVM运行代码使用

  • 注解是一个标签,有时候是做标记,有时候标记有属性

注解和python装饰器的区别

先说java的注解(Annotation),实际上是给语法元素打一个标记。比如你可以给一个函数打一个标记,给一个类打一个标记等等。Java只保证记录这个标记,但是不会主动根据这给标记做任何事。

比如,你在spring里,给一个私有成员打 @Autowired 这个标记。

public class XXXService {@Autowiredprivate XXXXRepository xxxxRepository;// ...}

如果你不用Spring框架的话,不会有任何事情发生,直接访问这个字段就是空。当如果你配置了合适的处理流程,而这个流程就会根据有没有这个标记干活。比如你要求Spring “Auto Scan” 并且注入依赖,这个处理过程会用反射去读哪些元素被做了某个特定标记。没有标记就不理,有标记就注入。

Python里的decorator是一个语法糖,是希望把“decorator”这个形式写得更漂亮。比如,你想记录一个函数开始执行之前和之后的log:

def foo():print("Hello")def logit(fn):def inner():print("before execute")fn()printf("after execute")return inner

这时,你可以魔改以下foo的实现,用logit这个“装饰器”来部分修改foo的行为,然后执行:

foo = logit(foo)foo()

但python里的语法可以让这个东西写成:

@logitdef foo():print("Hello")foo()

也就是说,python这里的装饰器是一个有逻辑的,可以执行的函数,只不过其写法有些特殊要求;而Java里面的Annotation只是个标记,需要其他代码来“根据标记执行“。

当然,装饰器模式是个很通用的东西,无论是python,java还是其他语言都可以写。只是python提供了特殊的语法糖而已。但java世界里做类似decorator的事情,希望动态魔改一个函数的行为,可以用动态代理或者aop

Java的Annotation因为相当于多加了一层(标记 + 处理逻辑),是一把双刃剑。好处是,在不动代码的情况下你可以通过外部配置来修改程序的行为。比如给一个函数打上@Test标。如果通过UT框架运行,这些打标的函数会被当作是测试用例;但如果外部直接用普通的main启动,这些@Test就会没有一样,不会影响代码本身的逻辑。但反过来,也容易引来一些问题。比如有的时候,你很难知道那个根据标记执行的逻辑是不是真的跑了。也许你哪里配置拼错一个字,或者classpath少依赖一个包,就造成那个逻辑并没有真的执行。这时从表面上也许很难看出来出错了。

感谢您的阅读,希望您对“Java中注解、元注解怎么用”这一关键问题有了一定的理解,具体使用情况还需要大家自己动手实验使用过才能领会,快去试试吧,如果想阅读更多相关知识点的文章,欢迎关注编程网精选频道!

--结束END--

本文标题: Java中注解、元注解怎么用

本文链接: https://www.lsjlt.com/news/321354.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 生态系统中流行库和框架的贡献指南
    作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
    99+
    2024-05-15
    框架 c++ 流行库 git
  • C++ 生态系统中流行库和框架的社区支持情况
    c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
    99+
    2024-05-15
    生态系统 社区支持 c++ overflow 标准库
  • c++中if elseif使用规则
    c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
    99+
    2024-05-15
    c++
  • c++中的继承怎么写
    继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
    99+
    2024-05-15
    c++
  • c++中如何使用类和对象掌握目标
    在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
    99+
    2024-05-15
    c++
  • c++中优先级是什么意思
    c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
    99+
    2024-05-15
    c++
  • c++中a+是什么意思
    c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
    99+
    2024-05-15
    c++
  • c++中a.b什么意思
    c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
    99+
    2024-05-15
    c++
  • C++ 并发编程库的优缺点
    c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
    99+
    2024-05-15
    c++ 并发编程
  • 如何在 Golang 中备份数据库?
    在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
    99+
    2024-05-15
    golang 数据库备份 mysql git 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作