該代碼不應編譯。
我相信你要麼犯了一個錯誤,導致你認爲它有效或者你的編譯器有bug。在Eclipse 4.5.1和javac 1.8.0_45中,getOrCreate
中的兩個return語句都給我提供了編譯錯誤。
說明
編輯:我改變了這樣的解釋,我想我誤解了問題的拳頭。
在說明我改變的getAndCreate
類型參數的名稱C
,以避免與其它類型的參數混淆。
問題是在asSubclass
方法中,類是C
的子類的信息丟失;唯一剩下的信息是該類是例如IdentifiedBusinessDSEntity
的子類。
asSubclass
有以下類型:
<U> Class<? extends U> asSubclass(Class<U> clazz)
我們可以看到接收機類,T
的原始類型的參數,是不存在的返回類型。
getOrCreate
被宣告返回C
。這就是您需要演員陣容的原因:要將C
類型重新引入返回值。
替代asSubclass
我們可以想像,asSubclass
有以下類型:
<U> Class<? extends U & T> asSubclass(Class<U> clazz)
這將是類型安全,並與返回類型代碼將編譯沒有轉換。但是Java中不允許使用像這樣的邊界的多個類型參數。
代碼
以下是我用來研究該問題的代碼:
class Test {
interface IdentifiedEntity {}
class BusinessDSEntity {}
class BusinessTransversalEntity {}
private <T extends IdentifiedBusinessTransversalEntity> T getOrCreateTransversalEntity(Class<T> classT, String id) {
return null;
}
private <T extends IdentifiedBusinessDSEntity> T getOrCreateDSEntity(Class<T> classT, String id) {
return null;
}
public abstract class IdentifiedBusinessDSEntity
extends BusinessDSEntity implements IdentifiedEntity {}
public abstract class IdentifiedBusinessTransversalEntity
extends BusinessTransversalEntity implements IdentifiedEntity {}
public <C extends IdentifiedEntity> C getOrCreate(Class<C> classT, String id) {
if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)) {
// Error here. Note that the type of s does not contain C.
Class<? extends IdentifiedBusinessDSEntity> s = classT.asSubclass(IdentifiedBusinessDSEntity.class);
return getOrCreateDSEntity(s, id);
} else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT)) {
// Also error here
return getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class), id);
}
return null;
}
}
可能的解決方法
我不認爲保留了大部分類型安全的任何真正優雅的解決方案。
一種替代方法是將返回類型的類傳遞給實體特定的方法。這相當難看且不方便,您必須手動驗證該類是否屬於正確的類型。
即使您丟失了某些類型的安全性,也可能只是施放返回值。
例子:
class Test {
interface IdentifiedEntity {}
class BusinessDSEntity {}
class BusinessTransversalEntity {}
private <R extends IdentifiedEntity, T extends IdentifiedBusinessDSEntity>
R getOrCreateDSEntity(Class<T> classT, Class<R> classR, String id)
{
// Verify that classT really is subclass of classR.
classT.asSubclass(classR);
return null;
}
private <R extends IdentifiedEntity, T extends IdentifiedBusinessTransversalEntity>
R getOrCreateTransversalEntity(Class<T> classT, Class<R> classR, String id)
{
// Verify that classT really is subclass of classR.
classT.asSubclass(classR);
return null;
}
public abstract class IdentifiedBusinessDSEntity
extends BusinessDSEntity implements IdentifiedEntity {}
public abstract class IdentifiedBusinessTransversalEntity
extends BusinessTransversalEntity implements IdentifiedEntity {}
public <C extends IdentifiedEntity> C getOrCreate(Class<C> classT, String id) {
if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)) {
return getOrCreateDSEntity(classT.asSubclass(IdentifiedBusinessDSEntity.class), classT, id);
} else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT)) {
return getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class), classT, id);
}
return null;
}
}
我再補充一點,編譯器錯誤是: – Javaddict
你能使其更簡單?簡單的名稱,完整的代碼,可重複的? – Amit
你使用什麼編譯器? – Lii