簡體   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