2016-09-03 30 views
2

Arrays.asList(..)返回數組的一個List包裝。這個包裝具有固定的大小,並直接支持數組,因此對add()或試圖修改列表的其他函數的調用將拋出UnsupportedOperationException異常。Arrays.asList是否違反了Liskov替換原則?

開發人員經常會對此感到驚訝,這一點從計算器中的問題可以看出。

然而列表界面具有add()方法應該意料之中連續工作列表的所有derivers,根據里氏替換原則(LSP)

IS)由Arrays.asList(返回的類型的一個例子是否違反了里斯科換人原則?

+1

編號'List.add'被記錄爲可選操作。 –

+0

@AndyTurner但不是可選操作違反LSP? –

+0

這不是一個「論壇」,不要稱之爲 –

回答

2

嚴格來說,它是因爲LSP沒有可選接口成員的概念:方法是接口的一部分,或者它不是接口的一部分。

但是,當Java類庫指定特定的接口方法爲可選時,它明確允許違反LSP。 List<T>.add()就是這樣一種方法。其他變異方法(addAll,remove等)也被標記爲可選。本質上,Java庫的設計人員採取了一種捷徑:與其爲可變列表(擴展只讀列表)創建單獨的界面,他們去指定操作「可選」。此外,他們還沒有提供一種方法讓您測試列表實例是否爲只讀,所以您唯一的選擇是捕獲運行時異常,這是一個非常糟糕的主意。這相當於你必須跟蹤你的名單來自哪裏,只有當你100%確定你的名單來源時才執行可選操作。

+0

這個解釋也是我傾向的方向。 –

+1

@ user889742 Right - LSP沒有「可選操作」的概念,一切都完全是二元的。 Java庫設計人員採取了一種捷徑,沒有爲只讀列表定義單獨的接口,而是通過可選操作創建了這個混亂。 – dasblinkenlight

0

如果你用非常專業的術語來思考它,那當然是違規了。 LSP指出,糟糕的設計是繼承的類不能使用超類方法的設計。 Java雖然並不總是關心違規行爲。正如你所建議的那樣,這通常是開發人員混淆的一種方式。 add()方法就是一個例子,remove()也是如此。這兩種都可用於不可變的列表,並且不能更改。好事是至少引發一個異常。

延伸閱讀:http://c2.com/cgi/wiki?UnmodifiableListIsStupidAndItBreaksLsp

+0

謝謝。我感覺合理。 –

+0

標記其中一個答案正確,如果有的話 –

2

我認爲這是不是違反LSP的。

LSP表示實現給定接口的類的所有實例都可以互換使用。

List.add(及其他變異方法)的文檔明確指出,該方法的實現可能會拋出UnsupportedOperationException

拋出

UnsupportedOperationException - 如果添加操作不受此列表

因此,如果支持你打算從未知來源調用此方法上的List實例,您需要處理add拋出UnsupportedOperationException的情況。

如果你不這樣做,你沒有正確使用API​​。


這並不是說我喜歡設計。我認爲嘗試調用該方法的事實是檢測實例上不支持任何給定方法的唯一方法是垃圾。我的意思是,嘿,給我們一個isAddSupported()方法(或類似)。

我只是沒有看到下面記錄的行爲可能會違反LSP。

+0

謝謝。但是我擔心,如果你可以用文檔來防止LSP違規,你可以寫在Rectangle.setWidth上//注意,可能不適用於矩形的所有派生類,然後從它派生出一個正方形,並說這符合LSP –

+0

@ user889742是的,你可以這樣做,你的班級的用戶需要處理它。理想情況下,您應該通過公認的文檔慣例來傳達它,如Javadoc中的'@ throws'節;但實際上,你在課堂公開文檔中寫的任何內容都是代碼寫入行爲的契約。 –

+0

@dasblinkenlight我實際上並不推薦捕捉異常。我說你需要知道它可能會發生。 –

相關問題