【问题标题】:bound mismatch error in java generic method when using self-referring type使用自引用类型时 java 泛型方法中的绑定不匹配错误
【发布时间】:2019-03-13 11:00:00
【问题描述】:

在泛型方法中使用自引用类型时出现绑定不匹配错误,但在泛型类声明中没有;这是错误代码的示例:

public class Container {
   public static class User<X> {}  // line 1
   public static class Box<U extends User<Box<U>>> {} // line 2
   public static class NiceBox<U extends User<Box<U>>> {}   // line 3: OK
   <U extends User<Box<U>>> void niceMethod(U user) {}   // line 4: NOT OK
}

第 4 行的编译错误消息:绑定不匹配:U 类型不是 有效替代 Container.Box&lt;U&gt; 类型的有界参数 < U extends Container.User<Container.Box<U>>>

我不明白为什么,在此先感谢您的帮助, SC

PS:请注意,与之前提出的问题不同,这里提出的问题仅存在于泛型方法中,编译器在泛型类声明中使用时接受有问题的类型绑定。

我正在使用最新 Eclipse 发行版随附的 Java 11 编译器。

这里有更多关于我想要实现的目标的详细信息。 我正在构建一个 Box,它需要在 C 类型的上下文中对 T 类型的目标执行一些工作,其中该上下文 C 必须满足最小接口。 然后我需要定义处理 Box 的方法(因此需要一个具有自引用类型绑定的泛型方法)。 代码如下:

static class Box<T,C extends MinimalContext<Box<T,C>>> {
    void doSomething(T target, C context) {
        // do something
    }
}

interface MinimalContext<B> {   
    boolean validate(B box);
    void print(B box);
}

// FAILS:
<T,C extends MinimalContext<Box<T,C>>>
void processBox(Box<T,C> box) {}   

// Instead use:
class BoxProcessor<T,C extends MinimalContext<Box<T,C>>>    
{
    BoxProcessor(Box<T,C> box) {
        // use box as niceMethod would do 
    }
}

请注意,由于限制只存在于泛型方法而不是类,我使用内部类来完成泛型方法的工作......还有其他解决方案吗?

eclipse 开发人员能否详细说明此限制?

【问题讨论】:

标签: java generics


【解决方案1】:

这似乎是 Eclipse 编译器的限制或更高级别的严格性。 javac 可以接受该代码。

在 Eclipse 中你可以这样写:

public static class User<T> {}
public static class Box<T extends User<Box<T>>> {}
<T extends User<Box<?>>> void niceMethod(T user) {}

然后你可以声明一个类:

static class UserBox extends User<Box<?>> {}

Eclipse 将允许您:

public static void main(String[] args)
{
    Container c = new Container();

    c.niceMethod(new UserBox());
}

但是它不会让你创建一个具体的Box。例如:

Box<UserBox> b = new Box<>();

Eclipse 不允许,但 javac 允许。

我怀疑 Eclipse 可能在做正确的事情,因为你在说:

Box 采用扩展 User 的类的类型参数,该类型参数具有 Box 的类型参数,该类型参数具有我们正在扩展的类型参数。”这对我来说听起来不可能,但我可能会错过一些东西。

编辑(因为问题已更新以显示界面):

与其将接口定义为完全通用并尝试在Box的定义中限制上下文类型,不如定义一个更具限制性的接口,例如:

interface BoxContext<B extends Box<?, ?>> {
    boolean validate(B box);
    void print(B box);
}

然后,您可以从 Box 的定义中删除自引用泛型:

static class Box<T, C extends BoxContext<?>> {
    void doSomething(T target, C context) {
        // do something
    }
}

然后允许您定义您的方法:

<T, C extends BoxContext<?>> void processBox(Box<T, C> box) {}

【讨论】:

  • 我将通过编辑我的问题来更多地描述这个问题。我也会说我是如何绕过限制的。
  • @stefanocasadei 我添加了另一个替代解决方案。
  • 我注意到在Box 类定义中,C 类型扩展了BoxContext&lt;?&gt; 而不是BoxContext&lt;B&gt;;只是想知道,这不会降低变量context 的可用性吗?例如方法context.validate() 不会知道它的参数是B
  • 否,因为接口已经定义了 validate 方法必须接受一个 Box,或者 Box 的子类。试试看!
  • 好的,我先试一试,然后在这里报告
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多