【问题标题】:Are the objects in the following class immutable?以下类中的对象是不可变的吗?
【发布时间】:2015-03-17 11:51:35
【问题描述】:
public class Point {
       private double x;
       private double y;
       Point (double x, double y) 
       { this.x = x; this.y = y; }
       double getX() { return x; }
       double getY() { return y; }       }

上述类中的对象是不可变的吗?解释。 我很困惑,因为 没有设置器,所以没有任何东西可以修改对象 但 它不应该包含最终变量或最终类。

如果类得到扩展,它可能会添加额外的非不可变字段,或者可以重写方法以每次返回不同的值。这不会使类不是不可变的吗?

【问题讨论】:

  • “对象在”,还是“对象”?
  • 在某些讨论中,“不可变”意味着所有字段都是final,并且像您这样的类具有非最终字段但从未更改的类称为“有效不可变”。类的构造函数与其他线程中调用的方法的同步方式存在一些差异,具体取决于该类是真正可变的还是仅有效不可变的。

标签: java multithreading class immutability mutable


【解决方案1】:

如果类得到扩展,...这些方法可以被重写以每次返回不同的值。这不是使类不是不可变的吗?

你的问题很微妙。如果某些class MutPoint extends Point 并覆盖getX()getY() 方法以返回非常量值,则不会更改Point 类本身。 Point sill 的实例实际上是不可变的,但允许调用者将 MutPoint 对象传递给 您的 方法,这些方法需要 Point 参数。那会发生什么?取决于您如何编写代码。 可能如果调用者给你一个 Point-like 对象,然后更改它的“值”,你的代码会表现得很糟糕。

如果您使用 Point 对象的代码要求它们永不更改,那么您可能需要声明整个类 final

public final class Point { ... }

这样,您的客户端将无法覆盖该类,并且不允许使用除实际 Point 实例之外的任何其他内容调用您的方法。

【讨论】:

  • 虽然该类的字段可能不会被改变,但是既然我们在构造函数中使用了“this.x”,那么它在构造过程中是否可以逃逸?
【解决方案2】:

是的,它们是不可变的。你可以在这里读到它 http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

【讨论】:

  • 但是 docs.oracle.com/javase/tutorial/essential/concurrency/... 提到的“final”关键字的使用不是必需的
  • 它说“并非所有记录为“不可变”的类都遵循这些规则”。还建议将您的课程设为最终课程以防止其扩展。最后,我会说这个类是不可变的,但有评论说它可以做得更好:)
  • 虽然这个类的字段可能不会被改变,但是由于我们在构造函数中使用了“this.x”,它是否可以在构造过程中逃逸从而使其可变?
  • @raj247 在构造函数中使用this 没有害处,但不要传递 this 作为任何属于另一个类的方法的参数,或者,任何可以被派生类覆盖的实例方法。这样做将允许其他类/派生类在实例完全初始化之前看到this。即使它是构造函数中的最后一条语句,也不要这样做,因为外部方法可能会将 this 引用传递给无法与构造函数调用正确同步的其他线程。
  • @jameslarge 我想我明白你在说什么,但我看不到清晰的画面。您能否为我提供一个示例以使事情更清楚..?感谢您的帮助..
【解决方案3】:

是的,因为您无法访问数据成员并且您没有更改数据成员的方法

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 2015-12-03
  • 2014-02-04
  • 2014-03-21
  • 1970-01-01
  • 2020-09-17
  • 2011-03-24
相关资源
最近更新 更多