Java构造函数和简单setter中参数命名的最佳实践

时间:2009-06-13 23:23:24

标签: java naming

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

I've seen the answer for 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,但我想知道什么是正确的做法。

13 个答案:

答案 0 :(得分:48)

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

答案 1 :(得分:19)

我也看到选项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中命名参数的最常用方法。

答案 2 :(得分:9)

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

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

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:3)

我知道当netbeans自动创建getter和setter时,它使用数字2方法。我个人通常会给变量加{,foo = tempfoo。但正如neesh所说,无论选择哪种方法,都应该保持一致

答案 5 :(得分: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.

答案 6 :(得分:1)

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

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

https://google-styleguide.googlecode.com/svn/trunk/javaguide.html#s5.2.6-parameter-names

答案 7 :(得分:1)

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

背后的原因非常简单: Clarity

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

this.bar = bar甚至bar = barbar = parBar更清晰,更直观?我宁愿有一个前缀而不是逻辑歧义。

答案 8 :(得分:0)

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

答案 9 :(得分:0)

选项二。

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

不这样做的通常原因是你可能会意外地写

...    foo = foo;

而不是

this.foo = foo;

这是一个没有做任何事情的参数的自我赋值。现代编译器捕获这一点 - 现代IDE在为字段创建setter时生成“this.foo = foo”语句。

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

答案 10 :(得分:0)

我使用的约定是用m_作为成员变量的序言;如:

String m_foo;

这样,很明显哪些变量是成员,哪些变量不是。

另外,我的上一家公司在方法中用“the”开头所有参数,如:

public doFoo(String theKey,String theRandom){

...

}

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

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

答案 11 :(得分:0)

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

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

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

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

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

答案 12 :(得分:0)

从设置器返回void很常见,但有时返回实例的引用很方便:

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");