使用getter方法的 'public static final' 或 'private static final'?

61

在Java中,通常建议将变量保持私有以实现更好的封装,但是对于静态常量呢?下面这段代码:

public static final int FOO = 5;

以下代码的结果与此相同:

private static final int FOO = 5;
...
public static getFoo() { return FOO; }

但哪种做法更好?


1
基于已经提供的主观反馈,投票关闭不具建设性。FOO真的是一个常量吗?提供FOO的类是API的一部分还是终端应用程序的一部分?有些数学常数永远不会改变。也有一些位标志永远不应该改变(请参见SWT)。所以答案是“这取决于情况”。 - Tim Bender
7个回答

76

直接在代码中使用常量的一个原因是不可取的。

假设FOO可能稍后更改(但仍保持不变),比如说 public static final int FOO = 10;。只要没人傻到直接硬编码该值,这应该不会有任何问题,对吧?

否定的。Java编译器将内联像上面的Foo这样的常量到调用代码中,即someFunc(FooClass.FOO); 变成 someFunc(5);。现在,如果重新编译库而不重新编译调用代码,你可能会遇到令人惊讶的情况。如果使用函数- JIT仍然会优化它,因此没有实际性能损失。


5
有趣,我从未意识到这一点。虽然我从未在实际应用中遇到过带有getter的常量。 - Adriaan Koster
4
取决于你的常数是什么 - 有很多不容改变的常数(例如 Pi 很有可能在这么多年后也不会变成 3 ;)),所以我不会谴责在所有情况下都使用公共常数。但是应该记住这一点,因为调试这样的问题非常糟糕。 - Voo
2
哇!+10!我已经做这个行业比我愿意透露的时间还要长了,我一直想知道为什么在看起来安全的情况下,我不应该只使用公共常量! - Stephen Hosking
1
对不起,我的英语不是很好,我没有看到正确的结论。有人能告诉我正确答案应该是什么吗? - 袁文涛
3
如果“常量”将来可能会更改,请使用getter。如果常量始终相同,则可以使用公共const。 - Voo
显示剩余2条评论

10

由于最终变量不能在以后更改,如果您将其用作全局常量,只需将其设置为public,无需getter。


9
只有当你绝对确定最终变量永远不会改变时,常量才会被编译器内联,如果稍后它们发生更改并且你没有重新编译所有内容,则可能导致非常令人惊讶的结果。编辑:我认为这个答案很有价值,可以使它更加突出。 - Voo

7

在这里使用Getter是没有意义的,而且很可能会被JVM内联。只需坚持使用公共常量即可。

封装背后的想法是保护变量不受意外更改,并隐藏内部表示。对于常量来说,这并没有太多意义。


4

将变量用作类外部:

public def FOO:Integer = 5; 

如果封装不是您的首选。否则,请使用第二种变体,以便公开方法而不是变量。
private static final int FOO = 5;
...
public static getFoo() { return FOO; }

不依赖变量是更好的代码维护实践。记住,“过早优化是万恶之源”。


1

如果getFoo的结果是常量且不需要在运行时评估,那么第一个if语句将会执行。


1

我会选择使用getFoo(),因为它允许你在不改变客户端代码的情况下将来修改实现方式。正如@Tomasz所指出的,JVM可能会内联你目前的实现,所以你不会支付太多性能的代价。


0
使用setter和getter在成员上的优点是能够进行重写。 这对于静态“方法”(更确切地说是函数)无效。
也没有办法定义接口的静态方法。
我会选择字段访问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接