返回Builder的工厂方法不使用泛型进行编译。怎么了?

| 我正在尝试构建一个API,客户端可以在其中注册接收事件的侦听器。在事件上调用的侦听器方法带有一个参数。 API应该让客户端决定该参数是具体类的实例还是接口的实例(以避免在客户端侦听器实现中进行不必要的强制转换)。为此,我使用了泛型。正常,除了一种情况! 客户端实现一个接口(请参见MyListener1Impl.java和MyListener2Impl.java中的示例),并且可以使用泛型来确定事件的参数类型。 静态工厂方法用于检索ClassABuilder.java的实例。 ClassABuilder \的build()方法返回ClassA.java的实例 由于某种原因,当将Factory方法与Builder模式一起使用(以伸缩形式调用方法)并且将具体的侦听器实现用作泛型类型参数时,它将无法编译(请参阅变量\“ c4 \”是组)。谁能告诉我为什么?怎么了? 请参阅下面的完整示例代码。将以下类复制/粘贴到Eclipse(或任何其他IDE)中,您将看到它无法编译的位置。 Main.java类
public class Main{
    public static void main(String[] args){
        // Works ok when generic type argument is set to interface \"AnyFile\".
        // MyListener2Impl has also declared \"AnyFile\"
        ClassABuilder<AnyFile> builder0 = Factory.newClassABuilder();
        builder0.set(new MyListener2Impl());
        ClassA<AnyFile> c0 = builder0.build();

        // Also Works ok when methods are called in telescope form 
        // (not sure \"telescope\" is the correct term?) 
        ClassA<AnyFile> c1 = Factory.newClassABuilder()
        .set(new MyListener2Impl())
        .build();

        // Works ok when generic type argument is set to concrete \"MyFileImpl\".
        // MyListener1Impl has also declared \"MyFileImple\"
        ClassABuilder<MyFileImpl> builder2 = Factory.newClassABuilder();
        builder2.set(new MyListener1Impl());
        ClassA<MyFileImpl> c2 = builder2.build();
        // also works ok with telescop form, but Factory class is NOT used.
        ClassA<MyFileImpl> c3 = new ClassABuilder<MyFileImpl>().set(new MyListener1Impl()).build();

        // But with static factory method AND telescope style, it does not compile! Why? What is wrong?
        ClassA<MyFileImpl> c4 = Factory.newClassABuilder()
        .set(new MyListener1Impl())
        .build();
    }
}
类AnyFile.java
import java.util.List;
public interface AnyFile {
    List<AnyFile> listFiles();
}
ClassA.java类
public class ClassA <T extends AnyFile>{
}
ClassABuilder.java类
public class ClassABuilder <T extends AnyFile>{
    public ClassABuilder<T> set(Listener<T> a){
        return this;
    }

    public ClassA<T> build(){
        return new ClassA<T>();
    }
}
类Factory.java
public class Factory {
    public static <T extends AnyFile> ClassABuilder<T> newClassABuilder(){
        return new ClassABuilder<T>();
    }
}
Listener.java类
public interface Listener <T extends AnyFile>{
    void event(T file);
}
类MyFileImpl.java
import java.util.List;
public class MyFileImpl implements AnyFile{
    @Override
    public List<AnyFile> listFiles() {
        // do something...
        return null;
    }
}
类MyListener1Impl.java
public class MyListener1Impl implements Listener<MyFileImpl>{
    @Override
    public void event(MyFileImpl file) {
        // do something
    }
}
类MyListener1Impl.java
public class MyListener2Impl implements Listener<AnyFile>{
    @Override
    public void event(AnyFile file) {
        // do something
    }
}
    
已邀请:
        简短的答案是Java的类型推断功能不足以从左到右进行推断。也就是说,在调用
.set()
方法之前,必须知道ѭ10the的类型
<T>
(将用于参数化
ClassA
),并且Java无法从在该返回类型上调用的方法的参数推断出
Factory.newClassABuilder()
的返回类型。 这种推断需要整个程序的分析,很少有语言会这样做,而Java绝对不支持。     

要回复问题请先登录注册