【问题标题】:Java Generic doesn't infer the typeJava Generic 不推断类型
【发布时间】:2018-06-12 11:28:02
【问题描述】:

我在下面编写了一个代码,该代码具有一个通用服务抽象类,该类具有该服务在其所有实现中需要执行的大部分通用功能。所有这些消息都需要经过验证,然后传递给各自的实现类,以便对那个对象做任何他们想做的事情

但这里的问题是 Java 编译器抱怨我下面代码中的参数 NotificationMessage 类型错误。

子类

谁能告诉我为什么以及如何解决这个问题?

我的 AbstractService 类:

public abstract class AbstractService<N extends NotificationMessage> implements ServiceInterface {

    @Override
    public boolean execute() {
        NotificationMessage notification = controller.load(); //this call would return object of sub-type of NotificationMessage
        processData(notification); //Compiler complains here that the argument is wrong here

    }

    protected abstract void processData(N notification);
    }
}

具体服务类之一:

public class SummaryService extends AbstractService<SummaryNotification> {

    @Override
    protected void processData(SummaryNotification notification) {


    }
}

数据对象:

public class NotificationMessage {
    public String getName() {
        return "";
    }
}




public class SummaryNotification extends NotificationMessage {
     public String getName() {
         return "";
     }

     public String getSummary() {
         return "";              
     }
}

【问题讨论】:

  • 您发布的代码永远不会编译。请向我们展示您正在处理的实际代码,或者至少是可以重现问题的最小实际版本
  • 您的代码中有拼写错误,例如return 被写成 rerun
  • 这是最小的实际代码,可能在将代码放在这里时做了太多更改,但它与我的代码相同,是的,在 processData(notification); 处存在编译器错误; ,就是这里的查询

标签: java generics compiler-errors


【解决方案1】:

你的方法:

protected void processData(SummaryNotification notification) {

接受SummaryNotification,因此您不能使用NotificationMessage 实例调用它。

(想象一下,如果您被允许这样做,在您的processData 方法中,您访问NotificationMessage 实例的方法getSummary,然后会发生运行时异常)

所以要么:

  1. 将您的 controller.load 更改为返回 SummaryNotification
  2. 让您的processData 接受NotificationMessage
  3. 如果您事先知道控制器将返回 SummaryNotification,请将您的 NotificationMessage 转换为 SummaryNotification(不建议这样做)

【讨论】:

  • 您好 Manh,感谢您查看我的查询。但是,这不是问题。我从具体类传递类型,该类接受它的参数。所以从具体类调用不是问题,如果我要取出我的具体类,抽象类本身不会编译,因为 processData(notification) 处的编译错误,应该调用它的抽象方法
  • @Ravi 不,您正在使用从控制器获得的 NotificationMessage 调用方法 processData(SummaryNotification notification)。无法保证会是 SummaryNotification,这就是编译器抱怨的原因。
  • @Ravi 你不能用NotificationMessage 实例调用processData。阅读Imagine 部分。
  • @daniu,你就在这里,这就是我从具体类传递类型的原因,我希望编译器能够推断出类型。所以我试图实现的基本思想是将类型传递给抽象类,抽象类使用始终是 NotificationMessage 子类型的类型并调用 processData(N notification)我>
  • @MạnhQuyếtNguyễn,但是在抽象方法中没有对 getSummary 的引用,它只是将它传递给具体类,具体类知道 SummaryNotification 的类型,它在 public class SummaryService extends AbstractService 中定义。
【解决方案2】:

使控制器也通用。

class Controller<N extends NotificationMessage> {
    public N load() { ...
}

并使用适当的控制器类型。

public abstract class AbstractService<N extends NotificationMessage> implements ServiceInterface {
    Controller<N> controller;

    @Override
    public boolean execute() {
        N notification = controller.load(); // this will return the correct subtype
        processData(notification); // Now notification is of the correct type

    }

    protected abstract void processData(N notification);
    }
}

【讨论】:

  • 很遗憾,不能这样做。这是一个旧的遗留代码,我们也不拥有它
  • @Ravi 在这种情况下,您无法确定控制器是否会创建正确的NotificationMessage,并且编译器的抱怨是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
相关资源
最近更新 更多