2017-09-27 160 views
0

我有一些接口(和完整性兩個虛擬類,所以你可以將代碼複製到您的IDE)瞭解泛型語法 - 泛型類型實現多個接口,參數

public interface ItfA 
{ 
    String getA(); 
} 

public interface ItfB 
{ 
    String getB(); 
} 

public class MyClassAdapter 
{ 
    public Object getValue(Object bean) 
    { 
     return null; // override to do something useful 
    } 
} 

public class MyClass 
{ 
    public MyClass(MyClassAdapter mca) 
    { 
     // do something useful with it 
    } 
} 

而且我有一些功能使用這些作爲參數(看起來有點怪異,但是這就是我必須使用他們(我不能改變MyClassAdapter))...

public <T extends ItfA> MyClass getMyClass(final Class<T> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA(); 
      } 
     } 
    ); 
} 

因此,我可以把這個getMyClass只與類實現接口ItfA - 其他人e編譯器會抱怨。

或者我也可以重寫此方法不指定泛型類型T作爲...

public MyClass getMyClass2(final Class<? extends ItfA> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA(); 
      } 
     } 
    ); 
} 

在某些情況下,我需要的類作爲實現多個接口參數 - 這將工作:

public <T extends ItfA & ItfB> MyClass getMyOtherClass(final Class<T> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA() + itf.cast(bean).getB(); 
      } 
     } 
    ); 
} 

但這個不起作用

public MyClass getMyOtherClass2(final Class<? extends ItfA & ItfB> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA() + itf.cast(bean).getB(); 
      } 
     } 
    ); 
} 

我不明白的區別betw een這兩種通用參數(<T extends ItfA>之前的方法名稱和使用Class<T>中的參數與參數中使用Class<? extends ItfA>相反) - 爲什麼兩種類型都使用一個接口,爲什麼一個接口有兩個接口,但另一個接口沒有。

任何提示?對我來說,第二個變種更具可讀性,所以我更喜歡這一點,但我不明白它與多個接口一起工作...

+0

無法調整'MyClassAdapter'確實可以保證您可以在這裏使用泛型獲得的功能。無論你在* compile *時間做什麼,你都被迫投射。您正在執行的演員*可能會在編譯時工作,但可能會在運行時崩潰。 – Makoto

+1

你知道所有的這些都等同於無反射'新MyClass的(新MyClassAdapter(){ @Override 公共 對象的getValue(對象豆) { 回報((ITFA)豆).getA(); } } );',對嗎? –

+1

@LouisWasserman:假設有一個''類...... – Makoto

回答

1

TypeParameter不同,TypeArgument不能有幾個邊界,所以<? extends ItfA & ItfB>無效。

這是我的猜測爲什麼是這樣的。

我認爲原因是TypeArgument需要特別有用。例如在Class<T>的情況下,方法cast返回T,您應該能夠聲明該類型的變量並將結果分配給它。

TypeArgument可以是:

  1. 類類別
  2. InterfaceType
  3. 的TypeVariable
  4. 數組類型
  5. 通配符

例1-4是沒有問題的,還有你總是有一些特定類型或類型變量。

如果是通配符,我們有WildcardBounds,例如<? extends IntfA>

如果你只允許一個上限,那麼你有一些特定的T。在Class<? extends IntfA>的情況下,您可以假定cast返回InfA

如果你允許更多的上限<? extends ItfA & ItfB>那麼問題是,你可以用什麼T呢?既然你在一般情況下沒有任何特定類型的T,那麼你可以做的最好的是Object,這不是很有用。

我認爲這是語言作者不能爲通配符類型參數指定多個上界的原因。

+0

好的,所以在一種情況下,參數有一個命名類型T(實現ItfA&ItfB),在另一種情況下,參數沒有類型。只有一個接口有一個命名類型T(它實現ItfA),或者參數類型ItfA - 好的,這很有道理,謝謝。 – outofmind