【问题标题】:Java class inner generic bound obscures parent interface generic bound definitionJava 类内部泛型绑定模糊了父接口泛型绑定定义
【发布时间】:2018-04-22 02:24:28
【问题描述】:

我有以下类结构,其中ProxyFactoryclass 的定义出现编译器错误:

错误:(32, 47) java: 类型参数 com.company.Factory.ProxyUpdatable 不在类型变量 T 的范围内

当我将ProxyUpdatable 的定义替换为简单地保存一个对象并删除它的类型参数时,代码编译得很好。

为什么ProxyUpdatable 的类型参数会影响它的工厂实现ProxyFactory 的边界?据我所知,向ProxyUpdatable 添加通用边界不会改变它实现的接口Updatable<ProxyUpdatable>

package com.company;

public abstract class Factory<T extends Factory.Updatable<T>> {

    public interface Updatable<T> {
        void copyFrom(T updated);
    }

    static class ConcreteUpdatable implements Updatable<ConcreteUpdatable> {
        @Override
        public void copyFrom(ConcreteUpdatable updated) {/* copyFrom implementation */}
    }

    static class ProxyUpdatable<T extends Updatable<T>> implements Updatable<ProxyUpdatable> {

        private final T implementation;

        ProxyUpdatable(T implementation) {
            this.implementation = implementation;
        }

        @Override
        public void copyFrom(ProxyUpdatable updated) {/* copyFrom implementation */}
    }

    static class ConcreteFactory extends Factory<ConcreteUpdatable> {
    }

    static class ProxyFactory extends Factory<ProxyUpdatable> {
    }
}

【问题讨论】:

  • 认为ProxyUpdateable 中的TFactory 必须采用的类型之间没有关系。虽然没有测试过。尝试更改类型变量名称,然后仔细查看源代码,可能会弹出一些内容。
  • ProxyUpdatable&lt;T extends Updatable&lt;T&gt;&gt; 转换为ProxyUpdatable&lt;P extends Updatable&lt;P&gt;&gt; 不能修复编译器错误。所以不知道为什么你认为它掩盖了一些东西。
  • @markspace 的关系是 ProxyFactory 将需要更新 Updatable 的任何可能实现。它通过在 Updatable.getClass() 上匹配,在内部委派一个更具体的 Factory T 实现来做到这一点。

标签: java generics polymorphism generic-programming


【解决方案1】:

停止使用原始类型!

似乎使用原始类型的行为会产生此编译器错误。 ProxyUpdatable 是泛型的,所以想用的时候加上泛型参数。

要解决此问题,请将ProxyUpdatable 的声明更改为:

static class ProxyUpdatable<T extends Updatable<T>> implements Updatable<ProxyUpdatable<T>> {

请注意,它现在实现了Updatable&lt;ProxyUpdatable&lt;T&gt;&gt;

然后您还必须更改ProxyFactory 的声明。您可以使其扩展 Factory&lt;ProxyUpdatable&lt;ConcreteUpdatable&gt;&gt; 或使 ProxyFactory 通用:

static class ProxyFactory<T extends Updatable<T>> extends Factory<ProxyUpdatable<T>> {

【讨论】:

  • 这是有道理的,虽然直到你发帖我才看到。现在ProxyUpdatable 中的T 类型与其超类中的T 相同。很好发现。
  • @Sweeper 不幸的是,我需要原始类型来隐藏代理的内部类型。代理工厂将需要通过委托给 T 工厂的具体实现来创建所有可能类型的 T 的 ProxyUpdatable 实例。所以 ProxyFactory 将创建 ProxyUpdatable 实例,其中 Instances 将是 ConcreteUpdatableA、ConcreteUpdatableB 等等
  • @Tunji_D 使用通配符怎么样?这有帮助吗? ProxyFactory extends Factory&lt;ProxyUpdatable&lt;?&gt;&gt;
  • @Tunji_D “不幸的是我需要一个原始类型来......”不,你不需要。原始类型应该在与 Java 5 之前的代码交互时使用。原始类型破坏了代码的类型安全性,因为您可以为具有泛型的参数传递任何类型(不仅仅是那些涉及省略的类型参数的参数),并且您可以将任何泛型返回值视为任何类型(尽管有警告)。通配符是正确的方法。
  • @Sweeper 我读错了你的第一个答案,替换原始类型有效!非常感谢
猜你喜欢
  • 2014-10-06
  • 2020-10-31
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
相关资源
最近更新 更多