为什么Java中没有常量功能?

Why is there no Constant feature in Java?

我试图找出Java中常量的原因
我了解到Java允许我们使用final关键字声明常量。

我的问题是为什么Java没有引入Constant(const)功能。 由于很多人说它来自C ++,在C ++中我们有const关键字。

请分享你的想法。


每次我从繁重的C ++编码转向Java,我都需要一点时间来适应Java中缺乏const-correctness的问题。如果您不知道,在C ++中使用const与仅声明常量变量有很大不同。本质上,它确保一个对象在通过一种称为const-pointer的特殊指针访问时是不可变的当在Java中,在我通常想要返回一个const指针的地方时,我改为返回一个带有接口类型的引用仅包含不应有副作用的方法。不幸的是,langauge没有强制执行。

维基百科提供以下有关该主题的信息:

Interestingly, the Java language specification regards const as a reserved keyword — i.e., one that cannot be used as variable identifier — but assigns no semantics to it. It is thought that the reservation of the keyword occurred to allow for an extension of the Java language to include C++-style const methods and pointer to const type. The enhancement request ticket in the Java Community Process for implementing const correctness in Java was closed in 2005, implying that const correctness will probably never find its way into the official Java specification.


const是什么意思
首先,要意识到"const"关键字的语义对不同的人意味着不同的东西:

  • 只读引用 - Java final语义 - 引用变量本身不能重新分配以指向另一个实例(内存位置),但实例本身是可修改的
  • 只读引用 - C const指针/引用语义 - 意味着此引用不能用于修改实例(例如,不能分配给实例变量,不能调用可变方法) - 仅影响引用变量,因此非const引用指向同一个实例可以修改实例
  • 不可变对象 - 表示实例本身不能被修改 - 适用于实例,因此不允许或不能使用任何非const引用来修改实例
  • 上面的一些组合?
  • 其他?

为什么或为什么不const
其次,如果你真的想深入研究一些"专业"与"反对"的论点,请参阅此增强请求(RFE)"bug"下的讨论。该RFE请求"可读参考"类型的"const"特征。在1999年开放,然后在2005年被Sun关闭/拒绝,"const"主题得到了激烈的争论:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

虽然双方都有很多好的论据,但反对const的一些常被引用(但不一定是引人注目或明确的)原因包括:

  • 可能有混淆语义,可能被滥用和/或滥用(参见上面的const是什么意思)
  • 可以复制其他可用的功能(例如,使用不可变接口设计不可变类)
  • 可能是特征蠕变,导致需要其他语义更改,例如支持按值传递对象

在任何人试图讨论这些是好是坏的原因之前,请注意这些不是我的理由。它们只是我从略读RFE讨论中收集到的一些原因的"要点"。我自己并不一定同意这些 - 我只是想引用为什么有些人(不是我)可能觉得const关键字可能不是一个好主意。就个人而言,我更喜欢以明确的方式将更多"const"语义引入语言。


C ++中的const并不意味着值是常量。

C ++中的const意味着合同的客户承诺不改变其价值。

如果您处于支持基于线程的并发的环境中,const表达式的值是否更改将变得更加明显。

由于Java从一开始就被设计为支持线程和锁并发,所以它不会因为重载术语而产生混淆,以获得final具有的语义。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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,但作为非const别名创建,x不是常量。并非每个编译器都需要volatile来执行此行为(尽管允许每个编译器内联常量)

对于更复杂的系统,您可以在不使用const_cast的情况下获得const /非const别名,因此养成认为const意味着某些内容不会改变的习惯变得越来越危险。 const仅仅意味着您的代码在没有强制转换的情况下无法更改它,而不是值是常量。


这是一个古老的问题,但我认为无论如何我会贡献我的2美分,因为这个话题在今天的谈话中出现了。

这并不完全回答为什么没有const?但是如何使你的类不可变。 (遗憾的是,我还没有足够的声誉作为对已接受答案的评论发布)

保证对象不变性的方法是更仔细地设计你的类是不可变的。这需要比可变类更多的关注。

这可以追溯到Josh Bloch的有效Java项目15 - 最小化可变性。如果你还没有读过这本书,那就拿起一本副本并阅读几遍,我保证它会提升你的比喻"java游戏"。

在项目15中,Bloch建议您应该限制类的可变性以确保对象的状态。

直接引用这本书:

An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is provided when it is created and is fixed for the lifetime of the object. The Java platform libraries contain many immutable classes, including String, the boxed primitive classes, and BigInte- ger and BigDecimal. There are many good reasons for this: Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.

然后Bloch通过遵循5个简单的规则来描述如何使您的类不可变:

  • 不提供任何修改对象状态的方法(即setter,aka mutators)
  • 确保无法扩展类(这意味着将类本身声明为final)。
  • 使所有字段final
  • 使所有字段private
  • 确保对任何可变组件的独占访问。 (通过制作对象的防御性副本)
  • 有关详细信息,我强烈建议您阅读本书的副本。


    const的C ++语义与Java final非常不同。如果设计师使用过const,则会产生不必要的混乱。

    const是一个保留字的事实表明设计师有实现const的想法,但他们已经决定反对它;看到这个封闭的bug。所述原因包括添加对C ++样式const的支持会导致兼容性问题。


    有一种方法可以在Java中创建"const"变量,但仅适用于特定的类。只需定义一个具有最终属性的类并将其子类化。然后使用你想要使用"const"的基类。同样,如果需要使用"const"方法,请将它们添加到基类中。编译器不允许您修改它认为是基类的最终方法的内容,但它将读取并调用子类上的方法。


    您可以使用static final创建类似于Const的东西,我过去曾使用过它。

    1
    2
    3
    4
    5
    6
    7
    8
    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;


    有两种方法可以定义常量 - conststatic final,具有完全相同的语义。此外,static final描述了比const更好的行为