46

对于简单的构造函数和设置器, Java中的参数是否有标准的可接受约定?

我已经看到了 C++ 的答案,但是两个社区之间的做法通常不同)

假设我有一个带有 foo 字段的 C 类。

我经常看到以下三个选项:

1)使用带下划线的实际字段名称:

public C(Type foo_)
{
   foo = foo_;
}

public void setFoo(Type foo_)
{
   foo = foo_;
}

2)使用实际的字段名称,只需在设置中使用“this”:

public C(Type foo)
{
   this.foo = foo;
}
public void setFoo(Type foo)
{
   this.foo = foo;
}

3)完全不一致的事情,例如:

public C(Type bar)
{
   this.foo = bar;
}
public void setFoo(Type bar)
{
   this.foo = bar;
}

我倾向于使用 2,但我想知道正确的做法是什么。

4

13 回答 13

53

选项二是最常见的。在 Java 中,使用无意义的名称前缀或后缀来区分实例变量、参数和局部变量被认为是不好的做法。但是名称本身没有约定。使用使代码最容易理解的任何名称。

于 2009-06-13T23:32:39.130 回答
21

我也将选项 2 视为最常见的选项:

int importance;

public int getImportance()
{
    return importance;
}

public void setFoo(int importance)
{
    this.importance = importance;
}

Eclipse 和 Netbeans 等 IDE 会自动按照上述格式编写 getter 和 setter。

使用这种方法有几个优点:

不要在字段名称中使用下划线 ( _) 字符 - 不建议将下划线用于非常量字段名称。

不建议在标识符中使用下划线字符,常量标识符除外。

The Java Tutorials 的Variables页面提到了以下关于下划线的内容:

如果您的变量存储一个常量值,例如static final int NUM_GEARS = 6,则约定会略有变化,将每个字母大写并用下划线分隔后续单词。按照惯例,下划线字符从不在其他地方使用。

(强调补充。)

由于字段名称不是常量,根据该页面上所写的内容,不应在非常量字段中使用下划线。

IDE 可以根据方法的参数名称自动添加 Javadoc 注释,因此在参数列表中包含字段名称将是有益的。

以下是自动生成的 Javadoc 的示例:

/**
 *
 * @param importance  <-- Parameter name in Javadoc matches
 *                        the parameter name in the code.
 */
public void setImportance(int importance)
{
    this.importance = importance;
}

让 Javadoc 反映字段名称还有另一个好处——具有代码完成功能的 IDE 可以使用 Javadoc 中的字段名称来自动填写参数名称:

// Code completion gives the following:
this.getImportance(importance);

为字段名称和参数名称赋予含义将更容易理解参数实际代表的内容。

这些是我目前能想到的一些优点,我相信这很可能是 Java 中命名参数的最常用方法。

于 2009-06-14T05:10:35.837 回答
9

(1) 非常 C/C++。Java 不太倾向于使用前导下划线。

我个人几乎完全使用(2)。

(3) 只是让你的生活变得困难,因为很难为成员和参数想出两个有意义但简洁的名称。

于 2009-06-13T23:35:02.057 回答
4

我见过 2 和 3 用得最多。也就是说,答案取决于您所贡献的代码库的公认标准。我认为在整个项目中保持一致比为每个 Java 开发人员都有一个“正确”的答案更重要。

Eclipse 代码生成使用列表中的样式 #2。

于 2009-06-13T23:30:20.180 回答
3

我知道当 netbeans 自动创建 getter 和 setter 时,它使用 2 号方法。我个人通常将 temp 添加到变量 iefoo = tempfoo中。但正如 neesh 所说,无论您选择哪种方法,您都应该尽量保持一致

于 2009-06-13T23:33:41.390 回答
1

是的,选项 2 使用最广泛;尽管它有一个严重的问题:如果您的参数声明中有错字 - 由于阴影可能会被忽视,例如:

class Whatever { 
  String val;
  Whatever(String va1) { this.val = val; }
  void printMe() { System.out.println(val.toString()); }
  public static void main(String[] args) {
    new Whatever("Hello").printMe();
  }
}

这段代码编译得很好;你需要一秒钟才能理解那里出了什么问题。如果您有疑问;打印出来;把它带给你的同事,问他们如果这个类被编译和执行会发生什么。我的猜测:75%+不会意识到会抛出 NullPointerException。如果你使用 val 和 va1 的“看起来一样”的字体;那么没有人会从阅读中注意到...

是的,现在您可能会看到有关此的警告,或者某些代码检查工具会告诉您发生了这种情况;当然,您的单元测试应该立即找到它。

但是:如果您避免这种模式,并使用前缀或“thatString”,您将永远不会遇到这个问题。因此,我真的不明白为什么它如此常用。

因此,我们在团队中坐下来,在整理我们的编码风格指南时,我们说:永远不要使用选项 2。

于 2014-01-16T07:43:41.513 回答
1

选项 2 是大多数 Java 风格指南所推荐的。

我发现 Google 的 Java 风格指南非常有用:

更新链接(2019 年 6 月): https ://google.github.io/styleguide/javaguide.html

或在网上搜索“Google Java 风格指南”

于 2015-04-08T18:36:30.177 回答
1

我个人使用foo(Bar parBar)虽然我知道它通常被认为是不好的做法前或后缀变量名。

背后的原因很简单:清晰

现在,如果你调用一个方法,它的实际含义foo(Bar bar)可能并不总是直观的。即使是这样,它仍然是一个痛苦的屁股。bar

如何比this.bar = barbar = bar干净、更直观bar = parBar?我宁愿有一个前缀而不是逻辑歧义。

于 2016-06-27T01:58:38.117 回答
0

当您编写代码以使界面尽可能清晰时,我总是更喜欢在_name内部使用字段,将其作为name方法参数,优雅地将其分配为_name = name. 我在 Fowler's Refactoring 和其他类似的教科书中看到了这一点,尽管我看到了丑陋的机制,例如在name内部使用该字段然后aName用作方法参数,呃。

于 2009-06-14T00:57:33.230 回答
0

选项二。

如果您看到“setFoo(String foo)”定义(例如在 javadoc 或 hover 中),您可以合理地预期字段“foo”被设置为参数“foo”的值。其他名称可能需要您仔细检查 - 例如 setName(String person) 是否只是将名称设置为 person 或者会采取其他操作(在人员表中查找名称等)?

不这样做的通常原因是你可能会不小心写

... 富 = 富;

代替

this.foo = foo;

这是参数的自分配,不做任何事情。现代编译器抓住了这一点——现代 IDE 在为字段创建 setter 时会生成“this.foo = foo”语句。

在 Eclipse 中,您可以为字段创建 getter 和 setter,当光标位于相关字段上时使用 Ctrl-1。

于 2009-06-14T11:12:34.440 回答
0

我使用的约定是在成员变量前面加上 m_;如:

字符串 m_foo;

这样,很清楚哪些变量是成员,哪些不是。

另外,我的上一家公司在方法中的所有论点都以“the”开头,如:

公共doFoo(字符串theKey,字符串theRandom){

……

}

它很容易不将参数与内部变量混淆。

约定应该是关于使代码更易于阅读并减少错误。

于 2009-06-14T13:07:37.080 回答
0

选项 2 在 Java 中最常见,但挑剔的 Checkstyle 不会让您使用此选项,因为本地 var 的名称会影响另一个。

因此,大多数使用以下内容:

foo(int thatBar) { this.bar = thatBar; }

使用此选项的唯一问题是其他人可能会猜测您在类中使用名为 bar 的 var,因为如果不是这样,您就不会这样命名参数。

邪恶的人只能通过查看方法来使用该信息来更好地理解您的课程。但是为此,您将使用一个混淆器来重命名所有变量等。

于 2013-05-15T13:36:27.573 回答
0

虽然void从 setter 返回很常见,但有时返回实例的引用很方便:

public class Foo {

    String value1, value2;

    public Foo setValue1(String value1) {
        this.value1 = value1;
        return this;
    }

    public Foo setValue2(String value2) {
        this.value2 = value2;
        return this;
    }
}

这允许您链接设置值:new Foo().setValue1("A").setValue2("B");

于 2019-04-05T13:48:29.723 回答