无法推断MFModel的类型参数<>

时间:2017-01-14 23:22:41

标签: java generics interface

我正在为我的论文做一个项目,无法解决以下问题......

在某些情况下,我有几种实现接口并扩展抽象类(实现接口部分)的方法。

MFModel是一个包装类,它封装了我的数据模型和数据流上某些操作所需的几个函数。

class MFModel<D extends IDataModel<?, ?>> {
        public MFModel() {}
        public MFModel(final D dataModel, final IPredictor<D> predictor, final ILearner learner) {}
}

RecDataModel是我的数据模型实现之一。

class RecDataModel implements IDataModel<Map<Long, Map<Long, Double>>, IDataStats> {}

BaselinePredictor是为我的模型数据提供操作的功能之一,同样适用于NullLearner

class BaselinePredictor
    extends AbstractModularFunction<IPredictor<IDataModel<?, IDataStats>>>
    implements IPredictor<IDataModel<?, IDataStats>> {}

class NullLearner implements ILearner {}

AbstractModularFunction<T>是一个抽象的部分实现接口。

abstract class AbstractModularFunction<T> implements IModularFunction<T> {}

以下接口定义了我的模型的数据内容,并为我的函数提供了可用的功能:

interface IDataModel<T, S> {}

interface IDataStats {}

interface IPredictor<D> extends IModularFunction<IPredictor<D>> {}

interface ILearner extends IModularFunction<ILearner> {}

interface IModularFunction<T> {}

在尝试实例化新的MFModel时,我遇到了以下问题:首先,如果我实例化ILearnerIPredictor<?>的已实现版本,我就不会警告或错误:

MFModel<?> okayModel = new MFModel<>(new RecDataModel(), new BaselinePredictor(), new NullLearner());

但是,如果我尝试使用这些接口,Eclipse会抛出cannot infer type arguments for MFModel<>错误:

ILearner learnerFunc = new NullLearner();
IPredictor<?> predictorFunc = new BaselinePredictor();
MFModel<?> problemModel = new MFModel<>(new RecDataModel(), predictorFunc, learnerFunc);
  

无法推断MFModel&lt;&gt;

的类型参数

如果省略菱形运算符,我可以编译并运行我的代码,然后反过来给我原始类型警告:

MFModel<?> warnModel = new MFModel(new RecDataModel(), predictorFunc, learnerFunc);
  

类型安全:构造函数MFModel(IDataModel,IPredictor,ILearner)属于原始类型MFModel。应该是泛型类型MFModel的引用        参数

由于我不喜欢抑制警告(或稍后接受可能的错误),我想知道类型参数错误源自何处。

这是一个显示我的问题的可运行代码段:http://ideone.com/K5BaIN

我很感激您可以给我的任何意见,因为我必须承认这些嵌套的仿制药对我来说很难掌握。它们降低了所需的强制转换和包装代码的数量,这就是为什么我要保留它们。此外,在某些情况下,由于模块化代码部分可以并且应该可以轻松地交换不同的实现,我无法确定我将获得哪种对象。

1 个答案:

答案 0 :(得分:1)

1。永远不要使用原始类型

出于兼容性原因允许使用它们,但是使用它们会首先破坏使用泛型的目的,因为它们违反了使用泛型所实现的几乎所有安全性和抽象性。

2。仅在需要时使用通配符

Wildcard表示对类型变量的存在量化,因​​此它们具有特殊用途。不应该使用它们来避免必须编写(并考虑)具体类型。如果您不想编写类型,您可以使用动态类型更多的语言。

考虑更换

IPredictor<?> predictorFunc = new BaselinePredictor();

使用以下两种陈述之一。

BaselinePredictor predictorFunc = new BaselinePredictor();
IPredictor<IDataModel<?, IDataStats>> predictorFunc = new BaselinePredictor();

即使

MFModel<?> okayModel = ...
当您尝试使用okayModel时,

会产生问题。

3。类型推断不是魔术

编译器使用其他表达式的类型推断某些表达式的类型。如果你拒绝提供具体类型的任何东西,那么类型推断将变得不可能。

在以下代码中,

ILearner learnerFunc = new NullLearner();
IPredictor<?> predictorFunc = new BaselinePredictor();
MFModel<?> problemModel = new MFModel<>(new RecDataModel(), predictorFunc, learnerFunc);
  • 您拒绝提供predictorFunc变量的编译器具体类型参数。
  • 您拒绝为MFModel构造函数提供编译器具体类型参数。
  • 您拒绝提供problemModel变量的编译器具体类型参数。

因此,以下错误是合理的。

  

无法推断MFModel&lt;&gt;

的类型参数

希望这有帮助。
祝你好运。