繁体   English   中英

具有泛型静态工厂的Java泛型拼图

[英]Java generics puzzler with generic static factory

我最近开始为一个项目编写一个通用的对象映射器,然后遇到了我不太了解的东西。 给定以下内容:

public class G<X> {
  public G(Class<X> c) { }

  public void m(X x) { }

  public static <T> G<T> create(Class<T> c) {
    return new G<T>(c);
  }

  public static void main(String[] args) {
    Object o = ""; // irrelevant!
    G<?> t = create(o.getClass());
    t.m(o);
  }
}

我收到以下编译错误:

m(capture#402 of ?) in G<capture#402 of ?> cannot be applied to (java.lang.Object)

我似乎无法找出一种方法来正确地投t ,使这个编译。 我想念什么? 使用JDK 1.6。

编辑

不是一个学术问题。 我正在尝试从休眠对象到它们对应的DTO编写一个映射器,以在REST层中传递。 假设对于每个ORM对象Foo ,可能存在一个类FooDTO ,该类具有一个构造函数,该构造函数将Foo一个实例作为参数。 如果FooDTO不存在或没有适当的构造函数, FooDTO Foo映射到FooDTO的泛型类将封装此假设并抛出适当的异常:

class Mapper<Foo,FooDTO> {
  private final Constructor<FooDTO> dtoConstructor;
  Mapper(Class<Foo> fooClass, Class<FooDTO> fooDTOClass){
    // find the constructor of FooDTO or throw ...
  }
  public FooDTO map(Foo f){
    return dtoConstructor.newInstance(f);
  }
  // this factory is for convenience when we don't know the type of FooDTO:
  public static Mapper<X,Object> create(Class<X> fromClass){
    Class<Object> dtoClass = // ... find it
    return new Mapper<X,Object>(fromClass,dtoClass);
  }
}

如果我传递通用对象类来create这似乎会中断。

请注意,我的实际实现中所有FooDTO类都从通用超类扩展而来,即, Mapper的签名实际上类似于Mapper<Foo,DTO<Foo>> 我认为这无关紧要。

编辑2

实际上,建议更改G<?> t = create(o.getClass()); G<Object> t = (G<Object>) create(o.getClass()); 在这种情况下工作。

不幸的是,我没有意识到我的课更复杂的事实实际上会产生影响。 这是一个更完整的示例(对于零星的问题,我深表歉意):

public class Y<T> {
}

public class G<X, Z extends Y<X>> {
  public G(Class<X> c, Class<Z> s) {
  }

  public void m(X x) {
  }

  public static <T, S extends Y<T>> G<T, S> create(Class<T> c) {
    Class<S> s = null; // find this via some reflection magic
    return new G<T, S>(c, s);
  }

  public static void main(String[] args) {
    Object o = ""; // irrelevant!
    G<? extends Object, Y<? extends Object>> t = create(o.getClass());
    t.m(o);
  }
}

在这种情况下,使用反射和该类型对象的某些常规位置创建对象Class<S> 该部分工作正常,应该与本讨论无关。 我现在收到的错误如下:

inconvertible types
found   : G<capture#155 of ? extends java.lang.Object,Y<capture#155 of ? extends java.lang.Object>>
required: G<java.lang.Object,Y<java.lang.Object>>

如果我将隐含的行更改为:

G<Object, Y<Object>> t = (G<Object, Y<Object>>) create(o.getClass());

我收到类似的错误:

java: inconvertible types
required: G<java.lang.Object,Y<java.lang.Object>>
found:    G<capture#1 of ? extends java.lang.Object,Y<capture#1 of ? extends java.lang.Object>>

再次,我为零散的信息表示歉意。 我在写作时正在对此进行分类。

您已经从getClass()方法传递了Class对象, 该方法返回Class<?> ,这意味着您必须将t声明为G<?>

当变量的通用类型参数是通配符时,不能使用通用类型参数调用方法。 编译器不知道通配符实际上是哪个特定类,因此在调用这种方法时不能保证类型安全。 这也是不能在List<?>上调用add的相同原因。

要使其编译,必须使用类文字,以避免使用Class<?> ,并声明t不具有通配符。

G<Object> t = create(Object.class);

然后

t.mo(o);

将编译。

您在这里拥有的是消费者。 但是,以下代码似乎可以编译(在Eclipse中)。

public static class G<X, Z extends Y<X>> {
    public G(Class<? extends X> c, Class<Z> s) {}
    public void m(X x) {}
    public static <T, S extends Y<T>> G<T, S> create(Class<? extends T> c) {
        Class<S> s = null; // find this via some reflection magic
        return new G<T, S>(c, s);
    }
    public static void main(String[] args) {
        Object o = ""; // irrelevant!
        create(o.getClass()).m(o);
    }
}

您正在创建一个G<Object> ,然后将其分配给G<?>类型的变量。 调用的方法采用通用类型的变量,而<?>则不接受任何类型。 如果将变量更改为G<Object> ,它将起作用。

由于您指定了G<?> ,因此javac期望找出泛型是什么(它们代表什么类)。 将语句更改为G t = create(o.getClass()); 解决错误。

capture错误通常意味着编译器无法找出类...

现在还不清楚您要做什么...也许这些信息将对您有所帮助...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM