Java是否具有引用所有权或不可复制类的概念?

时间:2016-11-03 11:27:03

标签: java

我想保证某些特定类Content的实例只能由其"所有者"访问,如果另一个对象需要相同的Content它需要深刻复印。来自C ++,我会用unique_ptr实现这一点,Java中是否有类似内容?

目前我正在解决这个问题,只需将Content保密,只保留一个,并注意在Content上创建一个新的getContent(构造函数实现深层复制机制) 。但我没有办法强制Content类的其他可能用户遵循相同的模式,这很容易忘记。如果它能以某种方式照顾自己会更好,就像不可复制一样。

我意识到这有点违背了语言的精神,但在某些情况下,我认为这是合理的。例如,如果Content代表某些数据流,即使通过读取它也会被修改。我想,如果不是核心语言,可能有一些@interface用于编译时检查或创建一个方法吗?

编辑:想法是所有者可以在复制之前或之后自由地修改对象,如果有人需要深层复制,他们可以修改它们(不影响原文),所以使Content不可变是有点过于苛刻(除非我误解了这意味着什么)。

4 个答案:

答案 0 :(得分:4)

这里有几个常见的策略:

隐私与防御性复制

在此策略中,您拥有所有者对内容的私有引用,如果它适合于提供该内容的副本,则可以执行此操作所以通过防御性副本:

class Owner {
    private Content content;

    // ...unnecessary detail omitted...

    public Content getContent() {
        return new Content(this.content);
    }
}

Cloneable interface有时在这里很有用。

不可变对象

另一种常见策略是使用不可变对象(例如,确保Content一旦实例化,就无法修改。那么你就不在乎谁拥有对内容的引用,因为他们无法改变它。

答案 1 :(得分:2)

不,没有。

一旦你建立了一个对象的引用,你就无法阻止某人通过已建立的引用来指定对该对象的另一个引用。

Java程序员通过使对象不可变(见java.lang.String)来解决这个问题。那么你不应该对其他人指的是特定的实例给出两个警告。

答案 2 :(得分:0)

您可以通过执行以下操作将类Content声明为Immutable:

  1. 不提供“setter”方法 - 修改字段引用的字段或对象的方法。
  2. 将所有字段设为最终字段并保密。
  3. 不允许子类覆盖方法。最简单的方法是将类声明为final。
  4. 如果实例字段包含对可变对象的引用,则不允许更改这些对象
  5. 这是一个java官方文档:https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

答案 3 :(得分:0)

Java没有类似的东西。有些语言元素可以帮助满足这些要求:

  1. 只有一个常量的枚举;被用作"内置"单身
  2. 用于创建不可变集合副本的集合中的方法
  3. 当然,你可以让你班上的所有领域都是最终的;所以它们只在施工期间进行初始化;以防止以后的更改
  4. 但是由于Java也缺少一个 const 概念,你可以部分解决这些问题。喜欢在:

    class Foo {
      private final List<Bar> bars = new ArrayList<>();
    

    并不意味着Foo的实例将不可变 - 因为您仍然可以添加/删除Foo拥有的列表中的元素。

    类似;给定

    List<Foo> root = ...
    List<Foo> immutableCopy = Collections.unmodifiableList(root);
    

    可以更改 immutableCopy ...搞乱 root