> 技术文档 > Java Record类介绍及使用

Java Record类介绍及使用


文章目录

  • 简介
  • Java Record类的核心特性‌
  • 与普通类的区别‌
  • 使用场景与最佳实践‌
  • jackson中的注解解释
  • 代码示例

简介

Java Record类是Java 14引入的预览特性,并在Java 16中正式成为标准功能,主要用于简化不可变数据载体的创建,自动生成构造方法、字段访问器、equals()、hashCode()和toString()等方法。

Java Record类的核心特性‌

  • 不可变性‌:所有字段默认是final的,实例化后不可修改,适合表示纯数据模型如DTO或值对象。‌‌

  • 自动生成方法‌:编译器自动生成全参数构造器、字段访问器(如name()而非getName())、equals()、hashCode()和toString()方法,显著减少样板代码。‌‌‌‌

  • 简洁语法‌:与传统类相比,Record类的声明更简洁。

例如:

public record Point(int x, int y) {}

等效于包含多个手动编写方法的普通类。‌‌

与普通类的区别‌

  • 继承限制‌:Record类隐式继承java.lang.Record,不能显式继承其他类,但可以实现接口。‌‌

  • 字段限制‌:仅能定义头部声明的字段,不支持额外实例变量(静态字段除外)。‌‌

  • 默认方法‌:自动生成规范方法,且不可重写父类方法(因父类为Record)。‌‌

使用场景与最佳实践‌

‌数据传输对象(DTO)‌:简化API请求/响应的数据封装。‌‌

‌不可变数据快照‌:如领域事件或配置参数,确保数据一致性。‌‌

‌扩展功能‌:
通过紧凑构造器实现参数校验:

public record User(String name) {public User { Objects.requireNonNull(name); }}

添加自定义方法(如计算衍生属性)。‌‌

jackson中的注解解释

  1. @JsonProperty :此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty(“name”)。 对属性名称重命名,比如在很多场景下Java对象的属性是按照规范的驼峰书写,但在数据库设计时使用的是下划线连接方式,此处在进行映射的时候 就可以使用该注解。
  2. @JsonIgnore此注解用于属性或者方法上(最好是属性上),用来完全忽略被注解的字段和方法对应的属性,即便这个字段或方法可以被自动检测到或者还有其 他的注解,一般标记在属性或者方法上,返回的json数据即不包含该属性。
  3. @JsonIgnoreProperties此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。
  4. @JsonFormat此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式。 例子:@JsonFormat(pattern=“yyyy-MM-dd hh:mm:ss”) @JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss”) private Date updateTime;
  5. @JsonSerialize此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。
  6. @JsonDeserialize此注解用于属性或者setter方法上,用于在反序列化时可以嵌入我们自定义的代码,类似于上面的@JsonSerialize。
  7. @JsonInclude 属性值为null的不参与序列化。例子:@JsonInclude(Include.NON_NULL)

代码示例

@Servicepublic class WeatherService { private static final String BASE_URL = \"https://api.weather.gov\"; private final RestClient restClient; public WeatherService() { this.restClient = RestClient.builder() .baseUrl(BASE_URL) .defaultHeader(\"Accept\", \"application/geo+json\") .defaultHeader(\"User-Agent\", \"WeatherApiClient/1.0 (your@email.com)\") .build(); } @JsonIgnoreProperties(ignoreUnknown = true) public record Points(@JsonProperty(\"properties\") Props properties) { @JsonIgnoreProperties(ignoreUnknown = true) public record Props(@JsonProperty(\"forecast\") String forecast) { } } @JsonIgnoreProperties(ignoreUnknown = true) public record Forecast(@JsonProperty(\"properties\") Props properties) { @JsonIgnoreProperties(ignoreUnknown = true) public record Props(@JsonProperty(\"periods\") List periods) { } @JsonIgnoreProperties(ignoreUnknown = true) public record Period(@JsonProperty(\"number\") Integer number, @JsonProperty(\"name\") String name, @JsonProperty(\"startTime\") String startTime, @JsonProperty(\"endTime\") String endTime, @JsonProperty(\"isDaytime\") Boolean isDayTime, @JsonProperty(\"temperature\") Integer temperature, @JsonProperty(\"temperatureUnit\") String temperatureUnit, @JsonProperty(\"temperatureTrend\") String temperatureTrend, @JsonProperty(\"probabilityOfPrecipitation\") Map probabilityOfPrecipitation, @JsonProperty(\"windSpeed\") String windSpeed, @JsonProperty(\"windDirection\") String windDirection, @JsonProperty(\"icon\") String icon, @JsonProperty(\"shortForecast\") String shortForecast, @JsonProperty(\"detailedForecast\") String detailedForecast) { } } @JsonIgnoreProperties(ignoreUnknown = true) public record Alert(@JsonProperty(\"features\") List features) { @JsonIgnoreProperties(ignoreUnknown = true) public record Feature(@JsonProperty(\"properties\") Properties properties) { } @JsonIgnoreProperties(ignoreUnknown = true) public record Properties(@JsonProperty(\"event\") String event, @JsonProperty(\"areaDesc\") String areaDesc,  @JsonProperty(\"severity\") String severity, @JsonProperty(\"description\") String description,  @JsonProperty(\"instruction\") String instruction) { } } /** * Get forecast for a specific latitude/longitude * @param latitude Latitude * @param longitude Longitude * @return The forecast for the given location * @throws RestClientException if the request fails */ @Tool(description = \"Get weather forecast for a specific latitude/longitude\") public String getWeatherForecastByLocation(double latitude, double longitude) { var points = restClient.get() .uri(\"/points/{latitude},{longitude}\", latitude, longitude) .retrieve() .body(Points.class); var forecast = restClient.get().uri(points.properties().forecast()).retrieve().body(Forecast.class); String forecastText = forecast.properties().periods().stream().map(p -> { return String.format(\"\"\"%s:Temperature: %s %sWind: %s %sForecast: %s\"\"\", p.name(), p.temperature(), p.temperatureUnit(), p.windSpeed(), p.windDirection(),  p.detailedForecast()); }).collect(Collectors.joining()); return forecastText; } /** * Get alerts for a specific area * @param state Area code. Two-letter US state code (e.g. CA, NY) * @return Human readable alert information * @throws RestClientException if the request fails */ @Tool(description = \"Get weather alerts for a US state. Input is Two-letter US state code (e.g. CA, NY)\") public String getAlerts(@ToolParam( description = \"Two-letter US state code (e.g. CA, NY\") String state) { Alert alert = restClient.get().uri(\"/alerts/active/area/{state}\", state).retrieve().body(Alert.class); return alert.features() .stream() .map(f -> String.format(\"\"\"Event: %sArea: %sSeverity: %sDescription: %sInstructions: %s\"\"\", f.properties().event(), f.properties.areaDesc(), f.properties.severity(), f.properties.description(), f.properties.instruction())) .collect(Collectors.joining(\"\\n\")); } public static void main(String[] args) { WeatherService client = new WeatherService(); System.out.println(client.getWeatherForecastByLocation(47.6062, -122.3321)); System.out.println(client.getAlerts(\"NY\")); }}
@JsonIgnoreProperties(ignoreUnknown = true)public record Points(@JsonProperty(\"properties\") Props properties) { @JsonIgnoreProperties(ignoreUnknown = true) public record Props(@JsonProperty(\"forecast\") String forecast) { }}相当于下面结构Points:{ \"properties\": { \"forecast\": \"晴天\", \"extraField\": \"会被忽略的值\" }, \"anotherExtra\": \"也会被忽略\"}@JsonIgnoreProperties(ignoreUnknown = true)public record Forecast(@JsonProperty(\"properties\") Props properties) { @JsonIgnoreProperties(ignoreUnknown = true) public record Props(@JsonProperty(\"periods\") List periods) { } @JsonIgnoreProperties(ignoreUnknown = true) public record Period(@JsonProperty(\"number\") Integer number, @JsonProperty(\"name\") String name, @JsonProperty(\"startTime\") String startTime, @JsonProperty(\"endTime\") String endTime, @JsonProperty(\"isDaytime\") Boolean isDayTime, @JsonProperty(\"temperature\") Integer temperature, @JsonProperty(\"temperatureUnit\") String temperatureUnit, @JsonProperty(\"temperatureTrend\") String temperatureTrend, @JsonProperty(\"probabilityOfPrecipitation\") Map probabilityOfPrecipitation, @JsonProperty(\"windSpeed\") String windSpeed, @JsonProperty(\"windDirection\") String windDirection, @JsonProperty(\"icon\") String icon, @JsonProperty(\"shortForecast\") String shortForecast, @JsonProperty(\"detailedForecast\") String detailedForecast) { }}相当于下面的结构:{ \"properties\": { \"periods\": [ { \"number\": 1, \"name\": \"Tonight\", \"startTime\": \"2023-11-01T18:00:00-05:00\", \"endTime\": \"2023-11-02T06:00:00-05:00\", \"isDaytime\": false, \"temperature\": 45, \"temperatureUnit\": \"F\", \"temperatureTrend\": \"rising\", \"probabilityOfPrecipitation\": { \"value\": 20, \"unit\": \"percent\" }, \"windSpeed\": \"5 to 10 mph\", \"windDirection\": \"SW\", \"icon\": \"https://api.weather.gov/icons/land/night/few?size=medium\", \"shortForecast\": \"Partly Cloudy\", \"detailedForecast\": \"Partly cloudy, with a low around 45. Southwest wind 5 to 10 mph.\" }, { \"number\": 2, \"name\": \"Wednesday\", \"startTime\": \"2023-11-02T06:00:00-05:00\", \"endTime\": \"2023-11-02T18:00:00-05:00\", \"isDaytime\": true, \"temperature\": 72, \"temperatureUnit\": \"F\", \"temperatureTrend\": null, \"probabilityOfPrecipitation\": { \"value\": 0, \"unit\": \"percent\" }, \"windSpeed\": \"10 mph\", \"windDirection\": \"W\", \"icon\": \"https://api.weather.gov/icons/land/day/skc?size=medium\", \"shortForecast\": \"Sunny\", \"detailedForecast\": \"Sunny, with a high near 72. West wind around 10 mph.\" } ] }}