我们真的需要 Java 中的静态最终常量吗?
假设我有以下代码:
public class Test {
public static final int A = 1234;
public static int getA()
{
return 1234;
}
}
您能否从效率方面比较以下两种情况?
Test.A
Test.getA()
我们真的需要 Java 中的静态最终常量吗?
假设我有以下代码:
public class Test {
public static final int A = 1234;
public static int getA()
{
return 1234;
}
}
您能否从效率方面比较以下两种情况?
Test.A
Test.getA()
假设一个 JIT 编译器,在效率上应该没有明显的差异 - 至少不足以对应用程序的执行速度产生显着影响。
但是,在灵活性方面有明显的提升:将值封装在方法中几乎总是好的,因为它可以让您更改以后计算值的方式。
该规则的一个值得注意的例外是纯常数,例如,来自数学世界:封装对 的访问没有多大意义Math.PI
,因为这个基本常数的值不可能改变,因此需要切换程序中获取值的方法。
常量的static
final
行为与从方法返回的文字值不同。在某些情况下,java 编译器也在编译时使用这些。
一个例子,
public static boolean DEBUG = false;
...
if (DEBUG)
{
...do something...
}
对比
public boolean debug()
{
return false;
}
...
if (debug())
{
...do something 2...
}
在第一种情况下,条件和...做某事...代码不会包含在编译的字节码(类文件)中。在第二种情况下,条件和 ...do something 2... 代码将被包含但从不执行 - 在这种情况下,JIT 可能会进行充分的分析,但会在运行时删除代码。
有一次,在 Java 的早期,JIT 不存在或不够聪明,无法优化返回文字值的简单方法。然后,性能需要一个恒定值。如果您记住外部类(用于公共/受保护的静态最终常量)将在编译时将值烘焙到该字节码中,那么以这种方式定义常量也更方便;而不是在运行时从源类中获取值。
在效率方面,test.getA()
往往可以test.A
通过 JIT 降低到相当于。尽管如此,这种差异充其量只能忽略不计。
我们真的需要 Java 中的静态最终常量吗?
不,但它有助于防止重复分配。
静态最终变量不能被外部代码更改,因此无需封装它们。
此外,没有参数的静态方法暗示访问对象的状态,这是一个谎言,因为该方法是静态的。
编译器方面的效率应该不会有太大差异,但在程序易读性和自文档代码方面,静态 final 是一个更好且经过时间考验的选择。
您展示的案例相当琐碎,我相信这是有意的。您的第一种情况更直接和更有效,因为它在堆栈上的调用更少,但我相信更好的编码风格是将两者结合起来。我认为这不会是您在课堂上使用此变量的唯一地方。
public class Test {
public static final int A = 1234;
public static int getA()
{
return A;
}
public static int doSomething()
{
int result = A * 10;
//do more stuff
return result;
}
}
这允许您仅在需要更改时在一个地方更改变量并在整个程序中获得预期的结果。就个人而言,我会将 int A 设为私有只是为了使用 get 方法的一致性,这就是必须设置类的方式。这样,您将永远不会遇到一个问题,即您不记得在变量名之后是否需要“()”,并且所有位于类之外的变量都以相同的方式访问。其中大部分只是编码风格,而不是对或错。