为什么Java泛型不支持通配符的OR子句



我正在处理这样一种情况,即我希望拥有类型的泛型

MyGeneric<T extends A | B>

即镜像的东西

MyGeneric<T extends A & B>

最后一个是允许的,给定B是一个接口;不接受B作为类的原因是Java不支持显式的多重继承。

从接受两种类型之一的Generic类中,我得到了一个确认,即我对泛型的OR子句的猜测对于Java来说是不可接受的。这意味着,无论B是类还是接口,我对OR子句的猜测在语法上都是不正确的。所以我想知道Java为什么不支持这一点。还有比"不执行"更有力的理由吗?

---编辑---

当然,在很多情况下,OR子句可能会引起怀疑(请参阅评论和答案),但看看我的案例:

public abstract class MyAbstractTask<T extends MyAbstractCommand> {
    @Override
    final protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if (result != null) {
           T response = null;
           Gson gson = new Gson();
           response = gson.fromJson(result, clazz);7
           postProcess(response);
        }
    }
    abstract void postProcess(T task);
}

在这种情况下,我正在应用模板方法模式+命令模式。所以T是命令,postProcess负责运行它

现在我可以拥有类似的东西

public class MyTask extends MyAbstractTask<MyCommand> {...}

而且很酷。

但是,假设您创建了一个"YourCommand"类。如果它与MyAbstractCommand无关,我将被迫复制报告的代码,或者创建一个由两个抽象命令实现的公共接口,或者让YourCommand扩展MyAbstract Command。如果支持OR子句,我可以将YourCommand添加到泛型的可接受参数类型列表中。

如果java泛型确实支持OR子句,那么注释中的问题呢:

<T extends Runnable | Callable<?>> void fun(T wtf)throws Exception{
      wtf.run(); // is this a compile time error?
      wtf.call(); // is this a compile time error?
}
void main(Runnable runnable, Callable<?> callable){
      fun(runnable); // is this a runtime error?
      fun(callable); // is this a runtime error?
}

Ceylon通过联合类型实现了这一点。由于JVM堆栈中存在这种语言,这意味着没有技术限制会禁止这种功能(我也想不出这样的限制)。尽管如此,有人可能会认为这样的功能不太可取,尤其是当语言支持mixin/ttrates/default方法时。

就我个人而言,我更喜欢使用接口分离原则和交集类型。这在可读性和可维护性方面要干净得多。当然,这并不总是可能的,尤其是在与第三方图书馆合作时。因此,这不是一个坏主意(我想Redhat的人也这么认为)。

因此,把这两个论点结合起来,就可以回答你的问题:

还有比"不执行"更有力的理由吗?

没有技术限制,但这不是一个好主意,因此它不是一个优先事项,而且可能不会持续很长时间。

最新更新