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

问题

我试图找出Java中常量的原因我已经了解到Java允许我们使用finalkeyword来声明常量。

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

请分享你的想法。


#1 热门回答(130 赞)

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

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

有趣的是,Java语言规范将const视为保留关键字 - 即,不能用作变量标识符的关键字 - 但不为其指定语义。人们认为关键字的保留是为了允许Java语言的扩展包括C-style const方法和指向const类型的指针。用于在Java中实现const正确性的Java Community Process中的增强请求票据于2005年关闭,这意味着const正确性可能永远不会进入官方Java规范。


#2 热门回答(78 赞)

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

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

为何或为何选择Notconst
其次,如果你真的想深入研究一些"专业"与"反对"的论点,请参阅此增强请求(RFE)"bug"下的讨论。该RFE请求"可读参考"类型的"const"特征。在1999年开放,然后在2005年被Sun关闭/拒绝,"const"主题得到了激烈的争论:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070
虽然双方都有很多好的论据,但一些经常被引用(但不一定引人注目或明确)的理由反对466475613包括:

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

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


#3 热门回答(6 赞)

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

constin C暗示合同的客户承诺不改变其价值。

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

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

例如:

#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标记为999107763,但作为非常量别名创建,x不是常量。并非每个编译器都需要volatile来执行此行为(尽管允许每个编译器内联常量)

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