为什么吸气剂和吸气剂如果返回值是可变的,则设置器?

发布于 2024-12-04 07:06:30 字数 263 浏览 2 评论 0原文

在 C++ 中,getter &由于能够通过 const 返回值控制可变性,因此私有数据成员的 setter 非常有用。

在Java中,如果我理解正确的话(如果我错了,请纠正我),在 getter 上指定 final 是行不通的。一旦调用者通过 getter 接收到数据成员引用,它就可以修改它,尽管它是私有的......

如果是这样的话(如果我在这里有一个严重的误解,请纠正我),为什么不声明数据成员 公开并简化事情?

In C++ a getter & setter for a private data member is very useful due to the ability to control mutability via a const return value.

In Java, if I understand correctly (please correct me if I am mistaken), specifying final on a getter doesn't work that way. Once the caller received the data member reference through the getter, it can modify it, despite it being private...

If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

笑红尘 2024-12-11 07:06:30

在 java 中使不可变返回值是一个或者返回已经不可变对象类型的问题(例如String)或返回非不可变对象的副本


示例 1 - 已经不可变的对象

public String getValue() {
    return value;
}

示例 2 - 已经不可变的对象的集合

public List<String> getValues() {
    return new ArrayList<String>(values);
}

示例 3 - 非不可变的对象

public Complex getComplex() {
    return complex.clone();
}

示例 4 > - 非不可变对象的集合

public List<Complex> getComplex() {
    List<Complex> copy = new ArrayList<Complex>(complexs.size());
    for (Complex c : complexs) 
        copy.add(c.clone());
    return copy;
}

示例 3 和 4 是为了方便起见,因为复杂类型实现了 Cloneable 接口。

此外,为了避免子类覆盖不可变方法,您可以将它们声明为final。附带说明一下, builder 模式通常很有用用于构造不可变对象。

Making immutable return values in java is a matter of either returning already immutable objects types (such as String) or returning a copy for non-immutable objects.


Sample 1 - Already immutable object

public String getValue() {
    return value;
}

Sample 2 - Collection of already immutable objects

public List<String> getValues() {
    return new ArrayList<String>(values);
}

Sample 3 - Non-immutable object

public Complex getComplex() {
    return complex.clone();
}

Sample 4 - Collection of non-immutable objects

public List<Complex> getComplex() {
    List<Complex> copy = new ArrayList<Complex>(complexs.size());
    for (Complex c : complexs) 
        copy.add(c.clone());
    return copy;
}

Sample 3 and 4 are for conveniance based on that the complex type implements the Cloneable interface.

Furthermore, to avoid subclasses overriding your immutable methods you can declare them final. As a side note, the builder pattern is typically useful for constructing immutable objects.

简单气质女生网名 2024-12-11 07:06:30

如果您希望您的类是不可变的(即只有 final 字段和 getter),您必须确保返回的值也是不可变的。返回字符串和内置基元时,您可以免费获得此功能,但是对于其他数据类型,需要一些额外的步骤:

  • 使用不可变装饰器包装集合,或者在从 getter 返回之前防御性地复制它们,
  • 复制 DateCalendar
  • 仅返回不可变对象或防御性地克隆它们。这也适用于集合中的对象。

请注意,如果您防御性地复制集合,则客户端可以查看或修改副本,但这不会影响原始集合:

return new ArrayList<Foo>(foos);

另一方面,如果您包装原始集合,则客户端能够看到引入的所有更改创建包装器后到集合,但尝试更改包装器的内容将导致运行时异常:

return Collections.unmodifiableList(foos);

底线是: Foo 也必须是不可变的,否则集合是不可变的,但客户端代码仍然可以修改集合的成员。因此同样的规则也适用于 Foo

如果是这种情况(如果我在这里有严重的误解,请纠正我),为什么不将数据成员声明为公共并简化事情?

因为:

  • 您可能希望将可变数据存储在对象内,并且只提供不可变(只读)数据的视图(例如包装集合),
  • 您可以在将来更改实现,摆脱字段,例如动态计算值。

If you want your class to be immutable (i.e. having only final fields and getters) you must be sure that the values you return are immutable as well. You get this for free when returning Strings and built-in primitives, however some extra steps are necessary for other data types:

  • wrap collections with immutable decorators or defensively copy them before returning from a getter
  • make a copy of Date and Calendar
  • Only return immutable objects or defensively clone them. This also applies to objects in collections.

Note that if you defensively copy a collection, the client can view or modify the copy, but this does not affect the original collection:

return new ArrayList<Foo>(foos);

On the other hand if you wrap the original collection, the client is able to see all the changes that were introduced to the collection after the wrapper was created, but trying to change the contents of the wrapper will result in runtime exception:

return Collections.unmodifiableList(foos);

The bottom line is: Foo has to be immutable as well, otherwise the collection is immutable, but the client code can still modify members of the collection. So the same rules apply to Foo.

If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?

Because:

  • you might wish to store mutable data inside an object and only provide immutable (read-only) view of the data (like wrapping collections)
  • you can change the implementation in the future, get rid of the field and for instance compute the value on the fly.
无戏配角 2024-12-11 07:06:30

如果您想返回可变标准容器(例如列表)的不可变视图,那么您应该查看 Collections 库:

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html

它提供了一些有用的包装器,例如 unmodifyingMap 和 unmodifyingList。这样您就不必制作浪费的副本。当然,如果列表的元素是可变的,那么这不会有太大帮助——Java 中没有简单的方法来获得“深度”不变性。当然,在 C++ 中也是如此——例如,如果您有一个指向 Foo 对象的指针的 const 向量,那么 Foo 对象本身仍然可以被修改(因为 const 不会跨指针传播)。

If you want to return an immutable view of a mutable standard container (eg list), then you should take a look at the Collections library:

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html

It provides some useful wrappers such as unmodifiableMap and unmodifiableList. That way you don't have to make a wasteful copy. Of course, if the elements of the list are mutable, then this won't help as much -- there's no easy way in Java to get "deep" immutability. Of course, the same is true in C++ -- e.g., if you have a const vector of pointers to Foo objects, then the Foo objects themselves can still be modified (because const doesn't propagate across pointers).

混浊又暗下来 2024-12-11 07:06:30

如果是这种情况(如果我在这里有严重的误解,请纠正我),为什么不将数据成员声明为公共并简化事情?

首先,JavaBeans 规范。要求您提供 getter(以及可变属性的 setter)。

其次,getter 可能使您能够添加一些逻辑,例如,一个 getter 可能实际上决定返回什么(例如,如果属性为 null,则返回一些不同的东西)。如果一开始就没有吸气剂,那么以后添加这样的逻辑就会遇到更多麻烦。使用吸气剂,您只需更改方法而无需接触调用者。

If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?

First of all, the JavaBeans spec. requires you to provide getters (and setters for mutable properties).

Second, getters might enable you to add some logic, e.g. one getter might actually decide what to return (e.g. if the property is null return something differenc). If you didn't have getters in the first place you'd have more trouble to add such logic later on. With getters you'd just change the method without touching the callers.

梦年海沫深 2024-12-11 07:06:30

为什么不将数据成员声明为公共并简化事情?

因为信息隐藏使得管理和维护复杂的代码库变得更加容易。如果数据成员是私有的,您可以在一个类中更改表示和行为,而不是在整个大型代码库中更改。

一旦调用者通过 getter 接收到数据成员引用,它就可以修改它,尽管它是私有的......

为了澄清,调用者不能修改从 getter 返回的数据成员。它也许能够修改数据成员指向的对象。

如果这是一个问题,并且您通过 getter 提供访问权限,则可以返回一个不可变的实例或防御性副本。

setter 对于控制对引用对象的修改也很有价值。您可以在二传手中制作防守副本。

why not declare the data member public and simplify things?

Because information hiding makes it easier to manage and maintain a complex codebase. If the data members are private, you can change representation and behavior in one class, rather than throughout a large codebase.

Once the caller received the data member reference through the getter, it can modify it, despite it being private...

To clarify, a caller cannot modify a data member returned from a getter. It might be able to modify an object to which the data member points.

If this is a problem, and you're providing access through a getter, you can return an immutable instance, or a defensive copy.

The setter is also valuable for controlling modification to a referenced object. You can make a defensive copy in the setter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文