在Java中自定义注解

部署运行你感兴趣的模型镜像

1.定义注解

JDK5开始引入注解,Java注解是一种在源码中添加元信息的机制。本文将创建一个自定义注解用来将对象转换为JSON字符串。

通过@interface关键字定义注解。

public @interface JsonSerializable {
}

接着通过Retention和Target定义元信息。 这个注解仅在运行时可见,并作用在类上。通过定义这个注解标记一个类,表示类可以被序列化为JSON。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
public @interface JsonSerializable {
}

接着创建第二个注解来标识类变量。这里通过方法定义了注解,表明有一个字符串参数key,默认值为空。当通过方法创建自定义注解,方法不能含有参数,不能抛出异常。返回值必须为原始类型,String,Class,enums,annotations及上述类型的构成的数组类型,默认值不能为null。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonElement {
    public String key() default "";
}

接着定义标记方法的注解,被标记的方法用来完成对象的初始化。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Init {
}

2.使用注解

下面定义了一个Person类,表示我们希望序列化的类。

@JsonSerializable
public class Person {
 
    @JsonElement
    private String firstName;
 
    @JsonElement
    private String lastName;
 
    @JsonElement(key = "personAge")
    private String age;
 
    private String address;
 
    @Init
    private void initNames() {
        this.firstName = this.firstName.substring(0, 1).toUpperCase() 
          + this.firstName.substring(1);
        this.lastName = this.lastName.substring(0, 1).toUpperCase() 
          + this.lastName.substring(1);
    }
 
    // Standard getters and setters
}

@JsonSerializable表明Person能被序列化为JSON字符串。被@JsonElement注解标记的字段才会被输出。@Init标记的方法将在序列化前执行。

3.注解处理器

接下来通过反射API来获取这些注解信息。

首先检查类是否被@JsonSerializable注解标记。

private void checkIfSerializable(Object object) {
    if (Objects.isNull(object)) {
        throw new JsonSerializationException("The object to serialize is null");
    }
         
    Class<?> clazz = object.getClass();
    if (!clazz.isAnnotationPresent(JsonSerializable.class)) {
        throw new JsonSerializationException("The class "
          + clazz.getSimpleName() 
          + " is not annotated with JsonSerializable");
    }
}

接着寻找被 @Init 注解标记的方法,并执行该方法来完成对象字段初始化。

private void initializeObject(Object object) throws Exception {
    Class<?> clazz = object.getClass();
    for (Method method : clazz.getDeclaredMethods()) {
        if (method.isAnnotationPresent(Init.class)) {
            method.setAccessible(true);
            method.invoke(object);
        }
    }
 }

接着检查被@JsonElement标记的字段,随后获取JSON元素的key与value,最后创建JSON字符串。

private String getJsonString(Object object) throws Exception {  
    Class<?> clazz = object.getClass();
    Map<String, String> jsonElementsMap = new HashMap<>();
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        if (field.isAnnotationPresent(JsonElement.class)) {
            jsonElementsMap.put(getKey(field), (String) field.get(object));
        }
    }       
      
    String jsonString = jsonElementsMap.entrySet()
        .stream()
        .map(entry -> "\"" + entry.getKey() + "\":\""
          + entry.getValue() + "\"")
        .collect(Collectors.joining(","));
    return "{" + jsonString + "}";
}

private String getKey(Field field) {
    String value = field.getAnnotation(JsonElement.class)
        .key();
    return value.isEmpty() ? field.getName() : value;
}

最后创建转换对象。

public class ObjectToJsonConverter {
    public String convertToJson(Object object) throws JsonSerializationException {
        try {
            checkIfSerializable(object);
            initializeObject(object);
            return getJsonString(object);
        } catch (Exception e) {
            throw new JsonSerializationException(e.getMessage());
        }
    }
}

验证结果

@Test
public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException {
    Person person = new Person("soufiane", "cheouati", "34");
    ObjectToJsonConverter serializer = new ObjectToJsonConverter();
    String jsonString = serializer.convertToJson(person);
    assertEquals(
      "{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}",
      jsonString);
}

4.总结

自定义注解的使用最终可以归纳为:

  1. 定义注解
  2. 在目标上使用注解
  3. 定义注解处理器
  4. 通过注解处理器使用被注解标注的目标

通过定义注解并使用可以简化代码,提供开发效率。

4.原文地址

https://www.baeldung.com/java-custom-annotation

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值