对于所提供的示例,最初的期望是错误的。发生 UnsupportedOperationException 的原因不同,而不是因为正在“写入”“只读”列表。仍然可以有“只读”列表。我希望下面的答案有助于澄清。
答案需要分两部分来考虑。一:ListProperty 异常,二:只读列表。
1) ListProperty 示例失败,因为尚未将列表分配给该属性。
这个简化的示例也会引发异常。请注意,任何“只读”方面都将被删除:
ListProperty<String> lp = new SimpleListProperty<>();
lp.add("element");
这可以通过以下方式纠正:
ObservableList ol = FXCollections.observableArrayList();
ListProperty<String> lp = new SimpleListProperty<>();
lp.setValue(ol);
lp.add("element");
如果我们以类似的方式更改原始示例,那么 ListProperty 和 ObservableList 示例都不会抛出异常,这不是 OP 想要或期望的。
2)第二部分问为什么可以将元素添加到只读列表中。使用 FXCollections.unmodifyingObservableList 创建只读列表将按预期抛出 UnsupportedOperationException:
ObservableList<String> ol = FXCollections.observableArrayList();
ObservableList<String> uol = FXCollections.unmodifiableObservableList(ol);
uol.add("element");
但这并没有回答为什么 ReadOnlyListWrapper/Property 不这样做的问题?
我们先来处理一下Property。 ListProperty 启用value进行更改,即它允许您为该属性分配不同的列表。 ReadOnlyListProperty 不允许这样做,即一旦分配了列表,它仍然是该列表对象。列表的内容仍然可以更改。下面的示例对于 ReadOnlyListProperty 没有任何意义:
ObservableList<String> ol1 = FXCollections.observableArrayList();
ObservableList<String> ol2 = FXCollections.observableArrayList();
ListProperty<String> lp = new SimpleListProperty<>(ol1);
lp.setValue(ol2);
所以只读指的是属性,而不是列表。
最后 - ReadOnlyListWrapper - 正如 API 文档所述“此类提供了一个方便的类来定义只读属性。它创建两个同步的属性。一个属性是只读的,可以传递给外部用户。另一个属性是读取的- 并且可写,并且只能在内部使用。”