什么是C ++的const成员函数的Java等价物?

在C ++中,我可以定义一个访问者成员函数,该函数返回私有数据成员的值(或引用),这样调用者就无法以任何方式修改该私有数据成员。

有没有办法在Java中这样做?

如果是这样,怎么样?

我知道final关键字,但AFAIK,当应用于一个方法时:

  1. 防止在子类中覆盖/多态化该方法。
  2. 使该方法可以内联。 (见@Joachim Sauer的评论如下)

但它并不限制方法返回对数据成员的引用,以致调用者无法修改它。

我忽略了一些明显的东西吗?

您要么返回不可变对象,要么返回私有实例变量的副本。 这样,对象的内部状态被“保护”免于修改,即:

 private MyMutableObject mutable = ... public MyMutableObject getMutableObject() { return new MyMutableObject(this.mutable); } ` 

Java中没有与C const “类型修饰符”相同的(遗憾的是)。

最接近的是在可变对象周围返回一个不可变对象或一个不可变包装器。

然而,不变性不是Java的语言特性,因此您将不得不依赖于库。

不可变对象的示例是:

  • 原始包装器IntegerCharacter ,..
  • String
  • File
  • URL

常用的不可变包装器(即防止突变的可变类型的包装器)是Collecton.unmodifiable*()方法返回的包装器。

这在java中不存在。 finalconst具有不同的语义,除非应用于基本类型的变量。 java解决方案通常涉及创建不可变类 – 其中对象在构造中初始化,并且不提供允许更改的访问器。 此类的示例可以是例如StringInteger

你没有忽视任何事情。 纯Java中没有办法这样做。 可能有些库使用注释提供了一些这样的子集,但我不知道任何副手。

传递对不可变数据的引用的方式是使您传递的类不可变,简单明了。 有一些库函数可以帮助您在一些非常有限但常见的情况下生成一些数据的不可变视图 。 这是一个例子:

 private List internalData; public List getSomeList() { return Collections.unmodifiableList(internalData); } 

您可以返回该成员的副本,因此更改不会反映在私有引用指向的对象中。 当然,对于原语,这个问题不存在。

但请注意内存使用情况! 对于所有情况,这可能不是正确的解决方案。 在这种情况下,另一个答案中建议的不可变对象可能是要走的路。

我不认为在Java中存在非原始对象的方法(你总是传递对这些对象的引用)。 你可以做的最接近的是返回一个对象的副本(使用克隆或类似的东西); 但这不是非常惯用的Java。

我只想访问成员对象的“可见”部分,您可以做的是创建一个带有可见部分的接口,并返回此接口。 例如 :

 public interface Bar { public int getBing(); } public class BarImpl implements Bar { private int bing; public int getBing() { return bing; } public void setBing(int bing) { this.bing = bing; } } public class Foo { private BarImpl bar; public Bar getNonModifiableBar() { return bar; // Caller won't be able to change the bing value, only read it. } } 

避免此问题的一种方法是不公开数据结构(另一种是返回副本或不可变包装器)

例如,而不是

 public List getSomeList(); 

 public String getSomeElement(int index); 

当你做这样的事情时:

 Object2 obj2 = obj1.getObj2(); obj2 = new Object2(); 

最初的私人成员(obj1.obj2)仍然像以前一样(只是为了确保你掌握了这个概念)。 你可以省略setter到obj2,这样内部字段就不会改变。

如果您希望Object2字段是不可变的,则需要应用相同的模式(私有字段,不设置setter)。

这回答你的问题?

取决于返回的对象以防止修改。 Java不提供对不可修改对象的声明/编译时检查,除非类型缺少mutator。

JDK中有一些支持:像Collection.unmodifiableCollection这样的方法将创建一个对象,如果客户端调用集合mutator方法,它将抛出运行时exception。

如果您真的很有动力,可以通过定义只读接口(或类)来进行编译时检查,这些接口只能自己公开/实现访问器方法。 请记住,仅仅声明方法返回只读接口不会阻止运行时修改,如果客户端使用内省并且对象提供了mutators(不抛出UnsupportedOperationException)。