Java Record类介绍及使用方法详解
作者:冉成未来
Record是Java新增的库类,在Java 14和Java 15中以预览(preview)形式公布,这篇文章主要介绍了Java Record类介绍及使用方法的相关资料,需要的朋友可以参考下
简介
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中的注解解释
- @JsonProperty :此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty(“name”)。 对属性名称重命名,比如在很多场景下Java对象的属性是按照规范的驼峰书写,但在数据库设计时使用的是下划线连接方式,此处在进行映射的时候 就可以使用该注解。
- @JsonIgnore此注解用于属性或者方法上(最好是属性上),用来完全忽略被注解的字段和方法对应的属性,即便这个字段或方法可以被自动检测到或者还有其 他的注解,一般标记在属性或者方法上,返回的json数据即不包含该属性。
- @JsonIgnoreProperties此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。
- @JsonFormat此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式。 例子:@JsonFormat(pattern=“yyyy-MM-dd hh:mm:ss”) @JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss”) private Date updateTime;
- @JsonSerialize此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。
- @JsonDeserialize此注解用于属性或者setter方法上,用于在反序列化时可以嵌入我们自定义的代码,类似于上面的@JsonSerialize。
- @JsonInclude 属性值为null的不参与序列化。例子:@JsonInclude(Include.NON_NULL)
代码示例
@Service
public 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<Period> 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<Feature> 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 %s
Wind: %s %s
Forecast: %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: %s
Area: %s
Severity: %s
Description: %s
Instructions: %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<Period> 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."
}
]
}
}
总结
到此这篇关于Java Record类介绍及使用方法的文章就介绍到这了,更多相关Java Record类使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
