2017-03-24 52 views
11

我想實現在Java中這樣的事情,但要編譯時錯誤:解決Java的泛型類型的錯誤與抽象類方法

The method onMessage(TextMessage, Class) in the type AbstractTestLoader is not applicable for the arguments (TextMessage, Class)

我理解錯誤的原因,但我也覺得應該有有些方法可以通過鑄造達到此目的,也可以採取其他方式。

public abstract class AbstractTestLoader<T extends AbstractEntity<T>> { 

    public void onMessage(TextMessage message) throws Exception { 
     onMessage(message, this.getClass()); // I want to correct this line in such a way so that I can call below method with actual Class of {T extends AbstractEntity<T>} 
    } 

    public void onMessage(TextMessage message, Class<T> clazz) throws Exception { 
     //here my original logic will go 
    } 
} 
+0

你爲什麼覺得*是這樣?也許你想增加對潛在問題的理解,以確保每個人都在同一頁面上。由於我們在探索解決方案空間時必須同意根本原因。 – GhostCat

+0

嗨@GhostCat,我已經嘗試用註釋行來探索我的底層問題'我想以這種方式糾正這一行,以便我可以用下面的方法調用實際類{T extends AbstractEntity }'也可以如果您想回答,請參考我發佈的解決方案以獲得更好的解決方案。 –

+0

'AbstractTestLoader'會成爲直接的超類嗎? – glee8e

回答

4

最後,嘗試幾次後,我只想找到簡單解決方案的工作,但我仍然很開放,如果能聽到其他最佳答案。謝謝

public abstract class AbstractTestLoader<T extends AbstractEntity<T>> { 

    abstract Class<T> getEntityType(); 

    public void onMessage(TextMessage message) throws Exception { 
     onMessage(message, getEntityType()); 
    } 

    public void onMessage(TextMessage message, Class<T> clazz) throws Exception { 
     //here my original logic will go 
    } 
} 
2

Java implements generics via type erasure,這意味着它只是一個編譯時的概念。程序運行時,AbstractTestLoader<Foo>AbstractTestLoader<Bar>之間沒有區別。

有幾個解決方法,就像您發現的那樣,在編譯時知道類型爲T的類可以提供實際的類類型。但是,使用純泛型無法在運行時發現泛型類型。

+0

其實,有一種方法。請參閱@ glee8e的回答 –

+0

@FedericoPeraltaSchaffner感謝您提及我,但@標記不會觸發系統通知給我,因爲該尾隨的's'使系統認爲您正在調用名爲'glee8e's'的人。只是一種提醒:) – glee8e

+0

@FedericoPeraltaSchaffner:glee8e的答案是一個很好的答案,並且在很多情況下可能會奏效。不過,我認爲它不會使我的答案無效,在我看來,它符合我提到的其中一個解決方法:「在編譯時知道'T'類型的類可以提供實際的類類型「。在維沙爾的回答中,它通過抽象方法來做到這一點;在glee8e的情況下,它通過要求消費類以特定方式進行聲明來實現。 – StriplingWarrior

5

應該注意的是,雖然Java通用在運行時被擦除,但如果它們存在於類文件中,則只有有限的反射apis才能檢索它們。

這裏是一個快速的解決方案與這些假設:

  1. AbstractTestLoader是直接超類。
  2. 子類在聲明超類時不使用類型通配符,例如像這樣的子類class GenericLoader<T extends SubclassAbstractEntity<T>> extends AbstractTestLoader<T>不存在。

下面是代碼:

public class AbstractTestLoader<T extends AbstractEntity<T>> { 

    private static final ClassValue<Class<?>> TYPE_PARAMETER_CACHE = new ClassValue<Class<?>>() { 
     @Override 
     protected Class<?> computeValue(Class<?> type) { 
      assert AbstractTestLoader.class.isAssignableFrom(type); 
      assert type.getSuperclass() == AbstractTestLoader.class; 
      Type genericSuperclass = type.getGenericSuperclass(); 
      assert genericSuperclass instanceof ParameterizedType; 
      Type entityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0]; 
      assert entityType instanceof Class<?>; 
      return (Class<?>) entityType; 
     } 
    }; 

    @SuppressWarnings("unchecked") 
    protected Class<T> getEntityType() { 
     return (Class<T>) TYPE_PARAMETER_CACHE.get(this.getClass()); 
    } 

    public void onMessage(Object message) throws Exception { 
     onMessage(message, getEntityType()); // getting compile time error here 
    } 

    public void onMessage(Object message, Class<T> clazz) throws Exception { 
     //here my original logic will go 
    } 
} 

getEntityType可以在子類在那兩個假設不能被重寫。