2017-01-17 97 views
0

我需要確保我的應用程序具有嚮應用程序擴展的超類引入新掛鉤方法的依賴項的向前兼容性。當我開始定義返回類型是已聲明的子類型時,直接引入新添加的方法(被我新構建的舊版本所忽略的方法)停止工作。覆蓋的Java方法即使存在,也不會調用

當我直接調用我的覆蓋方法爲foo.bar("")超類方法被調用。但是,當我通過從調試器foo.getClass().getMethod("bar", String.class).invoke(foo, "")反射調用它時,它會按預期調用重寫的方法。當它的返回類型被縮小到相同類型的重寫方法返回時,該方法被正確調用,它是之前的一個子類型。

回答

2

如果替換爲covariant return types,java編譯器將生成橋接方法,它們與其聲明的對應方具有相同的效果,但具有重寫方法的返回類型。這是JVM通過其名稱,參數列表來標識方法所需要的,並且與Java編程語言不同,它的返回類型也是如此。當且僅當知道該方法覆蓋並且返回的類型是由超類方法返回的類型的子類型時,編譯器纔會這樣做。 (請注意,該決定不取決於@Override註釋)。

在這種情況下,編譯器不知道新添加的方法應該是一個覆蓋(因爲舊版本的依賴關係根本沒有聲明它),因此無法知道協變的返回類型。結果,沒有生成的橋接方法會被JVM識別爲覆蓋,所以它最終在繼承樹的後面搜索方法實現。

有幾種方法可以解決此問題。

  • 確保壓倒一切方法確保向前兼容性這種方式具有相同的返回類型爲他們的父母。所以不需要橋接方法。
  • 針對新版本的依賴關係進行構建,並確保向後兼容。這裏最明顯的缺點是支持的最小版本不是maven POM聲明的版本。
  • 使用字節碼操作顯式生成橋接方法。我不提供鏈接來阻止讀者這樣做。
相關問題