我現在搜索並嘗試了一天以上,無法找到我在Java中遇到的常見問題的解決方案。原因很明顯 - 類型刪除。但我的問題是:在Java中這個問題真的沒有好的解決方案嗎?由於這類問題每次都會出現,所以我願意調查更多時間。Java工廠使用泛型,.class與.getClass()
我得到的錯誤是:
的方法doStrategy在IStrategy <捕獲#2的類型(?捕獲#2的延伸I)?擴展I>不適用於參數(I)
所以我簡化了下面的例子。
想象的模型:
package model;
public interface I {
//there are actual 30 classes implementing I...
}
public class A implements I {
public void someSpecificMagicForA(){
System.out.println("A");
}
}
public class B implements I {
public void someSpecificMagicForB() {
System.out.println("B");
}
}
和選擇邏輯
和通用戰略廠
package strategy;
import java.util.HashMap;
import java.util.Map;
import model.A;
import model.B;
public class StrategyFactory {
static {
strategies.put(A.class, AStrategy.class);
strategies.put(B.class, BStrategy.class);
}
private static final Map<Class<?>, Class<? extends IStrategy<?>>> strategies = new HashMap<>();
@SuppressWarnings("unchecked") // I am fine with that suppress warning
public <T> IStrategy<T> createStategy(Class<T> clazz){
Class<? extends IStrategy<?>> strategyClass = strategies.get(clazz);
assert(strategyClass != null);
try {
return (IStrategy<T>) strategyClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
這裏是測試
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import model.A;
import model.B;
import model.I;
import strategy.IStrategy;
import strategy.StrategyFactory;
public class TestCases extends TestCase {
public void testWithConcreteType(){
B b = new B();
StrategyFactory factory = new StrategyFactory();
IStrategy<B> createStategy = factory.createStategy(B.class);
createStategy.doStrategy(b); //awesome
}
public void testWithGenericType(){
List<I> instances = createTestData(); // image this is the business data
StrategyFactory factory = new StrategyFactory();
for (I current : instances){
IStrategy<? extends I> createStategy = factory.createStategy(current.getClass());
createStategy.doStrategy(current); //meh
//The method doStrategy(capture#2-of ? extends I) in the type IStrategy<capture#2-of ? extends I>
//is not applicable for the arguments (I)
}
}
private List<I> createTestData(){
A a = new A();
B b = new B();
List<I> instances = new ArrayList<>();
instances.add(a);
instances.add(b);
return instances;
}
}
我嘗試了另一種方法,使用番石榴TypeTokens(https://github.com/google/guava/wiki/ReflectionExplained)。但是我沒有設法做到這一點,因爲我真的沒有< T>,因爲我得到的是實現該接口的實例集合。
我有一個工作,並沒有那麼糟糕的解決方案,雖然使用訪問者模式。因爲我有真實的類
...visitor class
public void visit(A a){
doVisit(A.class, a); //private generic method now works of course
}
在編譯時再次一切都很好。但在這個特殊情況下,我花了相當長的時間來實現這個訪問者的超過30個子類。所以我真的想爲未來有一個更好的解決方案。
任何意見,非常感謝。
ohhhh!這很多.. – Satya
@ mr-lister thx編輯 - didn't知道&lt問題 - 但是有道理^^ – Rainer