元の期待は間違っています - 提供された例について。UnsupportedOperationException は別の理由で発生し、"読み取り専用" リストが "書き込まれている" ためではありません。「読み取り専用」リストを作成することも可能です。以下の回答が明確になることを願っています。
その答えは、2 つの部分で検討する必要があります。1 つ: ListProperty 例外と 2 つ: 読み取り専用リスト。
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) 2 番目の部分では、要素を読み取り専用リストに追加できる理由を尋ねます。FXCollections.unmodifiableObservableList を使用して読み取り専用リストを作成すると、予想どおり UnsupportedOperationException がスローされます。
ObservableList<String> ol = FXCollections.observableArrayList();
ObservableList<String> uol = FXCollections.unmodifiableObservableList(ol);
uol.add("element");
しかし、これはなぜ ReadOnlyListWrapper/Property がこれを行わないのかという質問には答えません。
最初にプロパティを扱いましょう。ListProperty を使用すると、値を変更できます。つまり、別のリストをプロパティに割り当てることができます。ReadOnlyListProperty はこれを許可しません。つまり、リストが割り当てられると、そのリスト オブジェクトのままになります。リストの内容は変更される可能性があります。以下の例は、ReadOnlyListProperty では意味がありません。
ObservableList<String> ol1 = FXCollections.observableArrayList();
ObservableList<String> ol2 = FXCollections.observableArrayList();
ListProperty<String> lp = new SimpleListProperty<>(ol1);
lp.setValue(ol2);
したがって、読み取り専用はリストではなくプロパティを参照します。
最後に - ReadOnlyListWrapper - API ドキュメントに記載されているように、「このクラスは、読み取り専用プロパティを定義するための便利なクラスを提供します。同期される 2 つのプロパティを作成します。1 つのプロパティは読み取り専用で、外部ユーザーに渡すことができます。もう 1 つのプロパティは読み取り専用です。 - 書き込み可能で、内部でのみ使用する必要があります。」