【问题标题】:Post Java-14 getter/setter naming convention后 Java-14 getter/setter 命名约定
【发布时间】:2020-05-15 18:38:41
【问题描述】:

Java 14 引入了records 功能。 Record 会创建与字段同名的 getter,例如,可以写成 print(person.name())。但是旧的 Java bean 约定规定应该将此方法命名为 getName()

在同一个代码库中使用这两种样式看起来不太好。将所有内容迁移到记录是不可能的,因为它们太有限而无法替换所有用例。

是否有任何官方或半官方指南如何在新代码中以 Java 14 命名 getter 和 setter?

【问题讨论】:

  • 我怀疑记录是一种不同于标准 javabean 的组件,也许它们遵循不同的约定是正确的。它们有不同的约束,所以它们自然不适合我们发现 javabean 的许多地方。
  • 我认为答案是否定的。还没有。风格指南/惯例倾向于跟踪添加新的语言特性,因为达成共识需要时间。
  • 此外...记录将只是 Java 14 中的“预览”功能。它们不一定会成为永久语言功能。
  • 就像一个数据点:Google 的 Java 目前广泛使用AutoValue,这是当前语言中的一种记录。从 getter 中省略“get”是一个相当普遍的约定;但有些人热切地推后(实际上,there's a specific point in the FAQ,说“做任何一个,只要保持一致”)。 YMMV; Google 风格只是众多选择之一。
  • @AndyTurner 对于我需要编写的 Groovy/Kotlin/EL 代码,我非常兴奋 obj.foo().bar.baz().quux

标签: java naming-conventions getter java-14 java-record


【解决方案1】:

引用JEP 359:

向样板宣战不是目标;特别是,使用 JavaBean 命名约定来解决可变类的问题并不是目标。

我的理解,基于同一个文档,记录transparent holders for shallowly immutable data

话虽这么说:

  1. 记录不是寻找 getter/setter 语法糖的地方,因为它们并不是要取代 JavaBeans。
  2. 我非常同意你的观点,JavaBeans 太冗长了。 也许可以实现一个附加功能(称为 beans 而不是 records) - 与 records 功能非常相似的行为但这将允许可变性。在这种情况下,recordsbeans 不会相互排斥。
  3. 如前所述,记录处于预览模式。让我们看看社区的反馈是什么。

总而言之,恕我直言,他们向前迈进了一步……我写了this example set,您可以看到代码从标准 JavaBeans 减少到 ~15% LOC。

另外,请注意records behave like normal classes: they can be declared top level or nested, they can be generic, they can implement interfaces(来自同一文档)。您实际上可以通过提取包含 getter 的接口来部分模拟 JavaBeans(不过只有 getter 才有意义)——但这将是很多工作,而且不是一个真正干净的解决方案......

因此,根据上述逻辑,为了解决您的问题, - 我没有看到任何(半)官方的 getter 和 setter 指南,我认为没有现在这样做的动机,因为,再一次,记录不是 JavaBeans 的替代品......

【讨论】:

    【解决方案2】:

    record 规范现在是"final" as of Java 17,遗憾的是,这种命名约定差异尚未得到解决。在尝试利用 Records 作为浅持有者类来实现现有领域模型的接口部分时,我偶然发现了它。

    虽然这不是我想要的那样简洁的解决方案,但 Records 可以有方法,因此您可以将“旧版”getter 添加到您的 record,如下面的(人为但简单)示例所示。

    public interface Nameable {
       public String getName();
    }
    
    public record Person(String name) implements Nameable {
       public String getName() {
          return name;   // or return name();
       }
    }
    

    至少这允许客户端代码继续使用久经考验的(超过 20 年的)约定,让我们面对现实吧,它的使用远远超过纯 JavaBeans 上下文。

    你可以说语言设计者没有辜负他们“不对样板宣战”的职责

    【讨论】:

    • 如果您确实需要访问器名称为getName,您是否考虑将您的组件命名为getName
    • 好吧,谢谢你的反对 - 不是......我,首先,我不太喜欢 record Person(String getName) 对我的代码的可读性所做的......我会说这是一个问题口味;就像命名约定一样。
    【解决方案3】:

    在 Java 记录中,对象字段必须是私有的和最终的。 所以只有一种 getter 和一种 setter 是可能的。

    在 Java 类中,对象字段可能是私有的或公共的。 在后一种类型的字段中,可以简单地通过添加句点和字段名称来获取或设置它们,例如

     Employee emp = new Employee(); // Nullary constructor
     emp.name = "John Schmidt";     // Setter
     . . . 
     . . . 
     if (emp.name != "Buddy")       // Getter
     {
        emp.bonus = 100.00;
     }
    

    非私有字段在 Android 应用中被大量使用,以节省内存和提取数据的时间。但是没有理由不在 Java 中使用它们,因为这样做是安全的。

    现在,如果您从 Java 类中的常用方式更改为记录类型中使用的方式,例如

    String name = emp.name();  // New getter convention for private field
    

    您很可能会被代码阅读者误解为非私有对象字段。

    如果您将记录获取器更改为 Java 对象中使用的内容,即

    obj.getField()
    

    那么编码审查员可能会混淆,并且编译器可能会将其视为 Java 对象,具体取决于执行决策标准。

    简而言之,它是与普通 Java 类或枚举不同类型的对象。它的访问者明确指出了这种新类型。 反正我就是这么看的。 也许 Java 开发委员会的某个人可以进一步启发我们。

    【讨论】:

    • 您注意到字段和方法位于不同的命名空间中吗?
    • 即使您将鼠标悬停在视野上阅读代码(我不怀疑您是否也这样做,伙计),这也不会立即跳转冲着你。 Eclipse 只是使用小的彩色方块和圆圈来表示名称空间。默认情况下,IntelliJ 甚至更节省。但我想您已将其配置为显示此重要信息。
    猜你喜欢
    • 2011-02-26
    • 2020-08-02
    • 1970-01-01
    • 2013-03-03
    • 2011-04-06
    • 2013-08-05
    相关资源
    最近更新 更多