双嵌套Java泛型

时间:2013-06-27 16:28:31

标签: java generics

今天早上我问了一个similar question,我以为我得到了答案,实际上已经实施了所提出的解决方案,但它没有按照我的需要去做。所以这是我的完整问题:

我有以下课程:

// Objects to process.
public class Apple {
    private Color color;
    private int numberOfSeeds;
    // ...
}

public class Chair {
    private Material madeOutOfMaterial;
    private double price;
    // ...
}

public class CellPhone {
    private Manufacturer make;
    private String model;
    private boolean isSmartPhone;
    // ...
}

// Contains the object that will be processed (an Apple, Chair, CellPhone instance, etc.)
// as well as metadata info about the processing itself (timestamp, a UUID for tracking
// purposes, etc.).
public class ProcessingMetadata<PROCESSABLE_OBJECT> {
    private PROCESSABLE_OBJECT result;
    private Date processedOnDate;
    private String uuid;
    // ...
}

// Abstract base class for processing PROCESSABLE_OBJECTs.
public abstract class ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
    private String name;

    public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}

// One concrete processor.
public class SimpleObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
    private Fizz fizz;

    @Override
    public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
        // Processes data one way, and returns a PROCESSABLE_OBJECT.
    }
}

// Another concrete processor.
public class ComplexObjectProcessor extends ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>> {
    private Buzz buzz;

    @Override
    public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
        // Processes data differently, and returns a PROCESSABLE_OBJECT.
    }
}

所以使用所有这些类的最终代码如下所示:

ObjectProcessor<ProcessingMetadata<Apple>> appleProcessor =
        new ComplexObjectProcessor<ProcessingMetadata<Apple>>();
Data data = getData();

ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);

Apple apple = meta.getResult();
Date processedOn = meta.getProcessedOnDate();
String uuid = meta.getUUID();

这是我想要向开发人员公开的“API”。获取一些Data,选择一个类型化的处理器,处理数据,并获得所需的所有元数据。

问题是我的ObjectProcessor<ProcessingMetadata<PROCESSABLE_OBJECT>>不合法。它在类定义的ProcessingMetadata部分给出了以下编译器错误:

  

令牌上的语法错误,错位的构造

我整个上午都玩过这个类(及其具体的子类),似乎无法正确设置泛型来给我提供我想要的API。我愿意要求PROCESSABLE_OBJECT实际上是一个界面,例如Processable,并AppleChair等实现它。但是不知道客户端想要处理什么,所以我不想强迫他们让POJO实现Processabl接口,如果可能的话。

那么,可能是我想要的API吗?如果是这样,怎么样?如果没有,那么为什么,我最接近它的是什么?提前谢谢!

3 个答案:

答案 0 :(得分:3)

类型参数列表中的每个项都需要是一个类型参数。在ObjectProcessor的类声明中,ProcessingMetadata<PROCESSABLE_OBJECT>不是泛型类型参数。

您可以将PROCESSABLE_OBJECT指定为参数化类型,然后指定将ProcessingMetaData扩展为另一个参数化类型的类型。

public abstract class ObjectProcessor< 
   PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>, 
   PROCESSABLE_OBJECT > 
{ ... }

修改

您的子类也是参数化类型。您需要在类本身上声明这些类型参数。然后你可以用它们来参数化超类。

public class SimpleObjectProcessor<
   PROCESSING_METADATA extends ProcessingMetadata<PROCESSABLE_OBJECT>, 
   PROCESSABLE_OBJECT > 
extends ObjectProcessor< PROCESSING_METADATA,PROCESSABLE_OBJECT > 
{ ... }

答案 1 :(得分:1)

我认为在你的api中,开发人员会使用这一行

ProcessingMetadata<PROCESSABLE_OBJECT> meta = appleProcessor.process(data);

这个

ProcessingMetadata<Apple> meta = appleProcessor.process(data);

答案 2 :(得分:0)

类声明本身只接受类型参数声明,但是你尝试将ProcessingMetadata放在那里。

public abstract class ObjectProcessor<PROCESSABLE_OBJECT> {
    private String name;

    public abstract ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data);
}

public class SimpleObjectProcessor<PROCESSABLE_OBJECT>
        extends ObjectProcessor<PROCESSABLE_OBJECT> {
    private Fizz fizz;

    @Override
    public ProcessingMetadata<PROCESSABLE_OBJECT> process(Data data) {
        // Processes data one way, and returns a PROCESSABLE_OBJECT.
    }
}

ObjectProcessor<Apple> appleProcessor = new ComplexObjectProcessor<Apple>();
// Note: there is no PROCESSABLE_OBJECT here. Use the concrete type:
ProcessingMetadata<Apple> meta = appleProcessor.process(data);