我试图找出Java中常量背后的原因我了解到Java允许我们使用final
关键字来声明常量。
我的问题是为什么 Java 没有引入一个 Constant ( const
) 特性。由于很多人说它来自 C++,所以在 C++ 中我们有const
关键字。
请分享你的想法。
每次我从繁重的 C++ 编码转到 Java 时,我都需要一些时间来适应 Java 中缺乏const 正确性的问题。const
如果您不知道的话,C++ 中的这种用法与仅声明常量变量有很大不同。本质上,它确保当通过一种称为 const 指针的特殊指针访问时对象是不可变的。在 Java 中,在我通常想要返回 const 指针的地方,我改为返回具有接口类型的引用仅包含不应有副作用的方法。不幸的是,这不是由语言强制执行的。
维基百科提供了有关该主题的以下信息:
有趣的是,Java 语言规范将 const 视为保留关键字——即不能用作变量标识符的关键字——但没有为其分配任何语义。人们认为保留关键字是为了允许对 Java 语言进行扩展,以包括 C++ 风格的 const 方法和指向 const 类型的指针。Java Community Process 中用于在 Java 中实现 const 正确性的增强请求票已于 2005 年关闭,这意味着 const 正确性可能永远不会进入官方 Java 规范。
什么const
意思
首先,要认识到“const”关键字的语义对不同的人意味着不同的东西:
final
语义 - 引用变量本身不能重新分配以指向另一个实例(内存位置),但实例本身是可修改的const
指针/引用语义 - 意味着此引用不能用于修改实例(例如,不能分配给实例变量,不能调用可变方法) - 仅影响引用变量,因此指向同一个实例可以修改实例为什么或为什么不const
其次,如果您真的想深入研究一些“赞成”与“反对”的论点,请参阅此增强请求(RFE)“错误”下的讨论。此 RFE 请求“只读参考”类型“const”功能。1999 年开放,然后在 2005 年被 Sun 关闭/拒绝,“const”话题引起了激烈的争论:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070
虽然双方都有很多很好的论据,但一些经常被引用(但不一定令人信服或明确)的反对理由const
包括:
const
)在有人试图争论这些是好是坏的理由之前,请注意这些不是我的理由。它们只是我从浏览 RFE 讨论中收集到的一些原因的“要点”。我自己不一定同意他们的观点——我只是想说明为什么有些人(不是我)可能觉得const
关键字可能不是一个好主意。就个人而言,我希望以明确的方式将更多“const”语义引入语言。
const
在 C++ 中并不意味着值是常量。
const
在 C++ 中意味着合约的客户承诺不改变其价值。
const
如果您处于支持基于线程的并发的环境中,则表达式的值是否更改会变得更加明显。
由于 Java 从一开始就被设计为支持线程和锁并发,所以它并没有因为重载该术语以具有所具有的语义而增加混乱final
。
例如:
#include <iostream>
int main ()
{
volatile const int x = 42;
std::cout << x << std::endl;
*const_cast<int*>(&x) = 7;
std::cout << x << std::endl;
return 0;
}
输出 42 然后 7。
虽然x
标记为const
,但作为一个非常量别名被创建,x
它不是一个常量。并非每个编译器都需要volatile
这种行为(尽管每个编译器都允许内联常量)
对于更复杂的系统,您会在不使用 的情况下获得 const/non-const 别名const_cast
,因此养成认为 const 意味着某些东西不会改变的习惯变得越来越危险。const
仅意味着您的代码在没有强制转换的情况下无法更改它,而不是该值是恒定的。
这是一个有点老的问题,但我想我无论如何都会贡献我的 2 美分,因为今天这个话题出现在对话中。
这并不能完全回答为什么没有 const?但是如何让你的类不可变。(不幸的是,我还没有足够的声誉作为对已接受答案的评论发表)
保证对象不变性的方法是更仔细地设计您的类以使其不可变。这比可变类需要更多的关注。
这可以追溯到 Josh Bloch 的Effective Java Item 15 - Minimize Mutability。如果你还没有读过这本书,那就拿起一本读几遍,我保证它会成为你比喻中的“java 游戏”。
在第 15 项中,布洛赫建议您应该限制类的可变性以确保对象的状态。
直接引用这本书:
不可变类只是一个实例不能被修改的类。每个实例中包含的所有信息都是在创建时提供的,并且在对象的生命周期内是固定的。Java 平台库包含许多不可变的类,包括 String、装箱的原始类以及 BigInteger 和 BigDecimal。这有很多很好的理由:不可变类比可变类更容易设计、实现和使用。它们更不容易出错并且更安全。
Bloch 然后描述了如何让你的类不可变,遵循 5 个简单的规则:
final
)。final
。private
。有关更多详细信息,我强烈建议您拿起这本书的副本。
的 C++ 语义const
与 Java 非常不同final
。如果设计师使用const
了它,那将会造成不必要的混乱。
这是一个保留字的事实const
表明设计者有实现的想法const
,但他们后来决定反对它;看到这个关闭的错误。所述原因包括添加对 C++ 样式的支持const
会导致兼容性问题。
您可以使用 static final 创建类似于 Const 的东西,我过去曾使用过它。
protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;
public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
有一种方法可以在 Java 中创建“const”变量,但仅限于特定的类。只需定义一个具有最终属性的类并将其子类化。然后在你想使用“const”的地方使用基类。同样,如果您需要使用“const”方法,请将它们添加到基类中。编译器不允许你修改它认为是基类的最终方法,但它会读取和调用子类上的方法。
有两种定义常量的方法 -const
和static final
,具有完全相同的语义。此外static final
,更好地描述了行为const