Java中与C++中的const等效的内容是什么?

24
我在想是否有Java中相当于c++中const的等价物。我了解final关键字,但不幸的是,我不能用它来声明函数返回值为final。它只能确保函数不会被覆盖,对吗?
基本上,我想确保给定的返回类不能被修改,并且是只读的。这在Java中可行吗?

1
出于好奇,你为什么想要对返回值施加这样的限制? - 6502
16
不可变性有助于避免许多错误。 - Tamás Szelei
假设类A有一个类B的字段,该类B又有一个类C的字段。如果类A在类B上调用getC()方法,则类A现在可以自由修改并可能破坏类C。 C++的const可以调节此行为。我只是好奇Java是否像C++一样标准化了这一点。 - lowq
2
@Brian,“static final”(不知道这里的静态有什么关系)是一个比c++中对象的“const”概念要不同得多,可惜它更弱。 - Voo
1
请参见https://dev59.com/VW445IYBdhLWcg3wO3xu#4971330。 - BlueRaja - Danny Pflughoeft
显示剩余3条评论
6个回答

21

基本上,我想确保返回的类不能被修改并且是只读的。在Java中有可能吗?

直接来说不行,但一个解决方法是使用 不可变 对象

例如 -

public final Foo {
    
    private final String s;
    
    public Foo(String s){
        this.s = s;
    }
    
    // Only provide an accessor!
    public String getString(){
        return s;
    }
}

3
你还应该在s的声明中添加final修饰符,以防止其他方法对其进行修改。(加1) - stacker
这是否意味着我必须为每个想要变成只读的类声明一个不可变对象的对应项? - lowq
13
在我看来,这是一个解决方法,不是等价物!除了这种极其冗长和容易出错的方法,没有其他解决这个问题的办法。 - Shautieh
@user984799 如果你将一个字段声明为final,它只能通过静态初始化或构造函数被赋值一次。请参阅第4.12.4章节的final变量,网址为http://java.sun.com/docs/books/jls/download/langspec-3.0.pdf。 - stacker
@user984799 - 不,它们不等同。在C++中,一个不可变对象并不等同于一个const限定的返回值。这是其中的一种解决方法。请看下面我的回答获取更多信息。 - Andy Thomas

15

Java不支持对象引用的const修饰。

解决方法包括以下几种:

  • 不可变对象
  • 修改后的对象的只读视图(例如,通过Collections.unmodifiable*()返回的视图)。
  • 只读接口类型
  • 防御性副本

不可变对象可以防止接收方进行修改,但它们也防止通过任何引用进行修改。它们与C++ const指针/引用不等价。

最接近的是只读接口类型。您可以将一个const-correct C++类映射到两个Java单元,一个接口仅包含const修饰的方法。

这在控制谁可以修改类实例时有时很有用。然而,它并不像在C++中那样经常使用。


4

“final”关键字表示常量。但是,在Java中使用final与C ++的用法有很大不同。 只有字段或局部变量可以是final。 final类不是const类,而是一种无法继承的封闭类。 final方法是一种密封方法,即无法重写的方法。

在C ++中存在“const类型”的概念,但是在Java中,您仅具有常量字段,常量方法(不可重写)和常量类(不可继承)的概念。


1

不支持

Java不支持C/C++中使用的constness概念。

无法编写与此Foo类等效的Java代码。

class Foo
{
public:
   std::vector<Bar>& bars( void ) const
   { return m_bars; }
private:
   std::vector<Bar> m_bars;
};

然而,Java有另一种方法,使用接口。

class Foo
{
public:
   ReadonlyList<Bar> bars( )
   { return m_bars; }
private:
   ArrayList<Bar> m_bars;
};

Java中的final关键字更类似于Foo * const而不是其他任何C++概念。请注意,Foo const*非常常见和有用,而Foo * const则不太常见。


你的代码应该写成:const std::vector<Bar>& bars( void ) const,否则它将无法编译。在C++中,你将无法调用返回的向量引用中的任何可变(非const)操作。就我所了解的Java而言,使用ReadOnlyList<Bar>,你不能修改ReadOnlyList,但仍然可以修改它包含的Bar。 - kyku

0

我认为你想要一个不可变对象。如果一个对象在构造后其状态无法更改,则被视为不可变。

为此,您需要:

确保类不能被覆盖 - 使类为final,或者使用静态工厂并将构造函数保持为private;使字段为private和final强制调用者一次性完全构造对象,而不是使用无参数构造函数结合后续调用setXXX方法;不要提供任何可以以任何方式更改对象状态的方法 - 不仅包括setXXX方法,还包括任何可以更改状态的方法。
示例代码: ``` public final class SomeThing{ public Something(String name) { fName = name; }
private final String fName;
public String getName() { return fName; } } ```

0

Java特别舍弃了C++的一些功能,其中之一就是const。这个有意识的决定可以从Java中保留了const作为保留字(但未使用)来反映。

设计师们可能认为这个功能真的很烦人,而且并不是非常有用。当我还是一个C++程序员时,我也有这种感觉。某些类型的静态检查只是太过于繁琐了。


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