【问题标题】:Multiple generic bounds including type parameter [duplicate]多个通用边界,包括类型参数
【发布时间】:2018-04-27 05:54:02
【问题描述】:

我想定义一个使用具有多个边界的类型的函数,其中一个边界是另一个类型参数。例如:

<A, R extends A & SomeInterface> R doSomething(...);

似乎(根据 Intellij IDEA)这是不允许的,任何具有多个边界的类型也不允许,其中任何一个边界都是类型参数。 所以这些都是非法的:

<A, R extends A & SomeInterface> R doSomething(...);
<A, B, R extends A & B> R doSomething(...);

但这些是合法的:

<R extends SomeType & SomeInterface> R doSomething(...);
<A, R extends A> R doSomething(...);

禁止扩展类型参数和接口的情况,但允许将类型参数替换为文字类型(类、枚举或接口)。如果根本不允许将类型参数作为边界,我会理解,但事实并非如此。我有什么遗漏吗?


如果这是一个 xy 问题,我要解决的确切问题是:

public interface Functor<A, Self extends Functor<?, Self>>
{
  <B, SelfB extends Self & Functor<B, Self>> SelfB map(Function<A, B> f);
}

上述声明,如果它是合法的,似乎提供了足够的约束来解决this problem;确保返回类型是相同类型的函子,以 B 作为其数据参数。 这是扩展接口和由类型参数确定的其他类型的情况。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    Java 有这样的限制,因为不能保证 &lt;A, R extends A &amp; SomeInterface&gt; R doSomething(...) 将适用于所有泛型类型A

    假设有SomeInterfaceAnotherInterface

    public interface SomeInterface {
        void foo();
    }
    
    public interface AnotherInterface {
        String foo();
    }
    

    也许你已经看到了问题

    假设你执行doSomething&lt;..., AnotherInterface&gt;(...) R 类型现在应该同时具有 void foo()String foo() 方法,由于签名冲突,这是不可能的。

    此外,我不确定doSomething&lt;..., SomeInterface&gt;(...) 的情况是否会得到正确处理:毕竟,接口不是其自身的子类型

    可能还有更多问题,尽管一个反例足以表明一般规则不起作用

    当您将特定类插入泛型参数时它会起作用,因为编译器能够推断您是否有冲突, 这就是为什么&lt;R extends SomeType &amp; SomeInterface&gt; R doSomething(...) 是合法的

    【讨论】:

    • 有人可能会争辩说,OP 提出的声明可能是合法的,而您在答案中提到的病态调用会触发编译时错误。
    • 为了使用这样的函数,您有时必须创建一个实现这两个接口的类的值(因为泛型方法本身不能创建泛型类型的值),并且这样做会导致编译时错误。因此,在这种情况下甚至不需要检查调用本身的类型。
    • 糟糕,我忘记了方法调用并不是唯一一次这样的限制(在第一条评论中提到的那个)会发挥作用,如果没有这个限制,有人可以用基于类的类型参数的不可用方法。
    • 所以我在想,防止分配给会导致不兼容边界的类型参数是最有意义的。但不阻止可能分配不兼容类型的通用边界。
    • @ZoeyHewll 看看这个stackoverflow.com/questions/197190/… 讨论持续了十年。简而言之,他们提出了同样的“错误类型”的想法。此外,这样做是为了限制它可能带来的不必要的复杂性。我喜欢这个>“......以排除某些尴尬情况的存在”如果没有某些示例,这没有多大意义,但可以说可以摆脱他的语言设计选择的问题)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2015-08-30
    • 2015-12-13
    • 2022-12-09
    • 1970-01-01
    相关资源
    最近更新 更多