使用泛型的Java工厂,.class vs..getClass()
我现在搜索和尝试了一天多,找不到解决Java中常见问题的方法。原因是显而易见的-类型擦除。但我的问题是:在Java中真的没有解决这个问题的好方法吗?我愿意调查更多的时间,因为这种问题每一次都会出现 我得到的错误是: 类型IStrategy中的方法doStrategy(capture#2-of?extends I)不适用于参数(I) 因此,我将问题简化为以下示例 想象一下模型:使用泛型的Java工厂,.class vs..getClass(),java,generics,reflection,factory,Java,Generics,Reflection,Factory,我现在搜索和尝试了一天多,找不到解决Java中常见问题的方法。原因是显而易见的-类型擦除。但我的问题是:在Java中真的没有解决这个问题的好方法吗?我愿意调查更多的时间,因为这种问题每一次都会出现 我得到的错误是: 类型IStrategy中的方法doStrategy(capture#2-of?extends I)不适用于参数(I) 因此,我将问题简化为以下示例 想象一下模型: package model; public interface I { //there are actual 30
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 model.A;
public interface IStrategy<T> {
public void doStrategy(T t);
}
public class AStrategy implements IStrategy<A> {
@Override
public void doStrategy(A a) {
a.someSpecificMagicForA();
}
}
public class BStrategy implements IStrategy<B> {
@Override
public void doStrategy(B b) {
b.someSpecificMagicForB();
}
}
在编译时一切都很好。但是在这个特殊的例子中,我花了相当长的时间来实现I的30多个子类的访问者。所以我真的希望将来有一个更好的解决方案
如有任何意见,我们将不胜感激 泛型是一种编译时功能,您只能使用编译器确定为安全的功能 注意:并非所有情况下都会删除该类型。例如,您可以获得
AStrategy
和BStrategy
的类型,因为它们是非动态的具体类型
AStrategy as = new AStrategy();
for(AnnotatedType asc : as.getClass().getAnnotatedInterfaces()) {
Type type = asc.getType();
System.out.println(type);
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
for (Type t : pt.getActualTypeArguments()){
System.out.println(t); // class A
}
}
}
印刷品
IStrategy<A>
class A
i战略
甲级
我不知道所有这些代码是否使您的解决方案更简单,但您可以获得正在实现的IStrategy类型,只要在编译类时知道它。泛型是编译时功能,您只能使用编译器确定为安全的功能 注意:并非所有情况下都会删除该类型。例如,您可以获得
AStrategy
和BStrategy
的类型,因为它们是非动态的具体类型
AStrategy as = new AStrategy();
for(AnnotatedType asc : as.getClass().getAnnotatedInterfaces()) {
Type type = asc.getType();
System.out.println(type);
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
for (Type t : pt.getActualTypeArguments()){
System.out.println(t); // class A
}
}
}
印刷品
IStrategy<A>
class A
i战略
甲级
我不知道所有这些代码是否使您的解决方案更简单,但您可以得到正在实现的IStrategy类型,只要在编译类时知道它。在Peter的回答和更多的研究之后,如果不以某种方式增强模型,我敢肯定这在Java中是不可能的。我决定继续使用访问者模式,因为在我看来编译时检查值得额外的代码 下面是我最后实现的内容(我相信你们都知道访问者模式——只是为了完整)
公共接口I{
公众访客(IVisitor访客);
//实际有30个类实现了I。。。
}
公共接口IVisitor{
公众访问(A);
公众访问(B);
}
public void testWithGenericType(){
List instances=createTestData();//image这是业务数据
StrategyFactory=新StrategyFactory();
访客=新访客(工厂);
对于(I:当前实例){
当前.接受访问者(访问者);
}
}
类访问者实现了IVisitor{
私人最终战略工厂;
公众访客(战略工厂){
这个工厂=工厂;
}
私人访问(课堂,T){
IStrategy createStategy=factory.createStategy(clazz);
createStategy.doStrategy(t);
}
@凌驾
公众参观(A){
doVisit(A.class,A);
}
@凌驾
公众参观(B){
doVisit(B级,B级);
}
}
希望这对其他人有帮助
问候,,
Rainer在Peter的回答和更多的研究之后,我非常确定,如果不以某种方式增强模型,在Java中这是不可能的。我决定继续使用访问者模式,因为在我看来编译时检查值得额外的代码 下面是我最后实现的内容(我相信你们都知道访问者模式——只是为了完整)
公共接口I{
公众访客(IVisitor访客);
//实际有30个类实现了I。。。
}
公共接口IVisitor{
公众访问(A);
公众访问(B);
}
public void testWithGenericType(){
List instances=createTestData();//image这是业务数据
StrategyFactory=新StrategyFactory();
访客=新访客(工厂);
对于(I:当前实例){
当前.接受访问者(访问者);
}
}
类访问者实现了IVisitor{
私人最终战略工厂;
公众访客(战略工厂){
这个工厂=工厂;
}
私人访问(课堂,T){
IStrategy createStategy=factory.createStategy(clazz);
createStategy.doStrategy(t);
}
@凌驾
公众参观(A){
doVisit(A.class,A);
}
@凌驾
公众参观(B){
doVisit(B级,B级);
}
}
希望这对其他人有帮助
问候,,
雷纳这个问题与擦除无关。这是因为Java的类型系统不够强大,无法在没有任何帮助的情况下静态地推理
current
和current.getClass()
之间的关系
在代码中:
for (I current : instances){
IStrategy<? extends I> createStategy = factory.createStategy(current.getClass());
createStategy.doStrategy(current);
}
这个函数的作用是有效地引入类型参数T
,它让Java知道我们打算在任何地方引用相同的未知类型T
。有了这些信息,它就可以理解我们从工厂获得的策略与我们的输入类所具有的类型是相同的,即类型签名中的currentcurrent
类型
不幸的是,当我们调用此方法时,仍然会出现编译错误:
for (I current : instances){
genericTestHelperDraft1(current.getClass(), current);
// Type error because current is not of type "capture of ? extends I"
}
这里的问题是类型系统不知道current
有自己的类型!Java的类型系统不理解currentfor (I current : instances){
IStrategy<? extends I> createStategy = factory.createStategy(current.getClass());
createStategy.doStrategy(current);
}
private <T> void genericTestHelperDraft1(Class<T> currentClass, T current) {
StrategyFactory factory = new StrategyFactory();
IStrategy<T> createStrategy = factory.createStategy(t);
createStrategy.doStrategy(current); // works
}
for (I current : instances){
genericTestHelperDraft1(current.getClass(), current);
// Type error because current is not of type "capture of ? extends I"
}
private <T> void genericTestHelperDraft2(Class<T> t, Object current) {
T currentDowncast = t.cast(current);
StrategyFactory factory = new StrategyFactory();
IStrategy<T> createStrategy = factory.createStategy(t);
createStrategy.doStrategy(currentDowncast);
}
for (I current : instances){
genericTestHelperDraft2(current.getClass(), current);
}