尝试在Java中构建可扩展的数据对象和适配器模式

时间:2011-11-11 00:30:49

标签: java reflection

我正在尝试使用适配器模式构建SDK。这是我到目前为止所得到的:

interface Adapter<T> {
  void doWork(WorkUnit<T> unit);
  Class<T> getT();
}

class WorkUnit<T> {
  public int getId() { ... }
  public T getExtras() { ... }
}

class OldWorkUnit {
  public <T> void setExtra(T data) { /* Store data in Map<Class, Object> */ }
  public <T> WorkUnit<T> toNewWorkUnit(Adapter<T> adapter) { /* Map.get(adapter.getT()) */ }
}

那里有很多泛型,但我在编译时无法知道T,并且可能有多个适配器,都有不同类型的T.这是为了暴露给第三方,所以我也在接口实现中需要尽可能少的实现,它必须是一个接口(没有抽象类)。

现在我想接受这个并用WorkUnit调用doWork。我在代码中的第一次传递看起来像这样:

class FooAdapter implements Adapter<FooWorkUnit> {
  ...
}

OldWorkUnit w = new OldWorkUnit();
w.setExtra(new FooWorkUnit());

Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);

a.doWork(unit);

哦,哦,不编译:

The method doWork(WorkUnit<capture#2-of ?>) in the type Adapter<capture#2-of ?> 
is not applicable for the arguments (WorkUnit<capture#4-of ?>)

我知道WorkUnit泛型参数与Adapter.doWork()泛型参数的类型相同,但不知道类型我无法正确地转换它。

那么有没有办法解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

为什么在这里通配模板类?:

Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);

如果你这样做:

Adapter<FooWorkUnit> a = new FooAdapter();
WorkUnit<FooWorkUnit> unit = w.toNewWorkUnit(a);

这不能保留您的需求吗?

现在编译器知道FooWorkUnit是共同点,可以这么说。

编辑:关于运行时可变性的确定点。如何强力键入执行工作的方法,以便消除通配符,但仍然是一致的:

@SuppressWarnings("unchecked")
public <X> void prepareArgsAndDoTheWork() {
    OldWorkUnit w = new OldWorkUnit();
    w.setExtra(new FooWorkUnit());

    Adapter<X> a = (Adapter<X>) ... ; // Obtain the Adapter by reflection etc 
    WorkUnit<X> unit = w.toNewWorkUnit(a);
    a.doWork(unit);
}