从Java开发开始学习的第一件事就是如何将一个类声明到其自己的文件中。 可能的后期阶段包括:
但这并不仅限于此: JLS充满了惊喜。 我最近了解到可以在任何块(包括方法)中声明类。 这称为本地类声明(第14.3节) 。
本地类是一个嵌套类(第8节),它不是任何类的成员,并且具有名称。 所有本地类都是内部类(第8.1.3节)。 每个本地类声明语句都立即包含在一个块中。 本地类声明语句可以与块中的其他种类的语句自由混合。
紧接在块中的局部类的范围(第14.2节)是紧接在其后的块的其余部分,包括其自己的类声明。 紧接在开关块语句组(第14.11节)中的局部类的范围是紧接着封闭的开关块语句组的其余部分,包括其自己的类声明。
不错,不是吗? 但是仅出于此目的使用它还不够...直到本周为止:我开始在非Boot应用程序中实现诸如Spring Boot Actuator之类的功能,使用Jackson序列化结果。
Jackson提供了几种自定义序列化过程的方法。 对于只需要隐藏字段或更改其名称以及对象无法使用的类的对象,它提供了mixins 。 例如,让我们调整以下类的序列化:
publicclassPerson{
privatefinalStringfirstName;
privatefinalStringlastName;
publicPerson(StringfirstName,StringlastName){
this.firstName=firstName;
this.lastName=lastName;
}
publicStringgetFirstName(){
returnfirstName;
}
publicStringgetLastName(){
returnlastName;
}
}
假设要求是具有givenName
和familyName
属性。 在常规的Spring应用程序中,应在配置消息转换器的过程中注册mixin类:
publicclassWebConfigurationextendsWebMvcConfigurerAdapter{
@Override
publicvoidconfigureMessageConverters(List<HttpMessageConverter<?>>converters){
MappingJackson2HttpMessageConverterjackson2HttpMessageConverter=newMappingJackson2HttpMessageConverter();
jackson2HttpMessageConverter.getObjectMapper().addMixIn(Person.class,PersonMixin.class);
converters.add(jackson2HttpMessageConverter);
}
}
现在,在什么地方声明此mixin类最有意义? 在最小范围内声明某些内容的原则适用:将其保存在专用文件中显然是错误的,但即使是私有嵌套类也不过分。 因此,最受限制的范围是方法本身:
publicclassWebConfigurationextendsWebMvcConfigurerAdapter{
@Override
publicvoidconfigureMessageConverters(List<HttpMessageConverter<?>>converters){
MappingJackson2HttpMessageConverterjackson2HttpMessageConverter=newMappingJackson2HttpMessageConverter();
abstractclassPersonMixin{
@JsonProperty("givenName")abstractStringgetFirstName();
@JsonProperty("familyName")abstractStringgetLastName();
}
jackson2HttpMessageConverter.getObjectMapper().addMixIn(Person.class,PersonMixin.class);
converters.add(jackson2HttpMessageConverter);
}
}
尽管从纯软件工程的角度来看这种方式是合理的,但是有一个理由不设计这样的代码: 最小惊喜原则 。 除非团队的每个成员都了解并熟悉本地课程,否则不应使用此功能。
翻译自: https://blog.frankel.ch/use-case-for-local-class-declaration/