2013-01-21 92 views
2

我已經切換到Java 7構建21並開始得到奇怪的編譯錯誤。例如,下面的代碼片段不編譯(儘管的IntelliJ不顯示任何錯誤):泛型:與通配符類型編譯錯誤

1 Iterable<?> parts = ImmutableList.<String>of("one", "two"); 
    2 Function<?, String> function = new Function<Object, String>() { 
    3 @Override 
    4 public String apply(final Object input) { 
    5  return input.toString(); 
    6 } 
    7 }; 
    8 Iterable<String> result = Iterables.transform(parts, function); 
    9 System.out.println(result); 

但如果我在第2行替換?Object

2 Function<Object, String> function = new Function<Object, String>() { 

然後編譯成功。

我得到的錯誤是略帶神祕:

error: method transform in class Iterables cannot be applied to given types; 
required: Iterable<F>,Function<? super F,? extends T> 
found: Iterable<CAP#1>,Function<CAP#2,String> 
reason: no instance(s) of type variable(s) F,T exist so that argument type Function<CAP#2,String> 
conforms to formal parameter type Function<? super F,? extends T> 
where F,T are type-variables: 
F extends Object declared in method <F,T>transform(Iterable<F>,Function<? super F,? extends T>) 
T extends Object declared in method <F,T>transform(Iterable<F>,Function<? super F,? extends T>) 
where CAP#1,CAP#2 are fresh type-variables: 
CAP#1 extends Object from capture of ? 
CAP#2 extends Object from capture of ? extends Object 

更改線2是

2 Function<? extends Object, String> function = new Function<Object, String>() { 

沒有效果。

我正在使用JDK 1.7.0_11-b21;這用於編譯確定構建4.

這是一個javac錯誤或我的?

+0

請注意,將剛剛創建的'Function '分配給'Function '沒有任何價值。你知道它是一個'Function ',因爲你剛創建它,不需要丟掉編譯器在那裏的信息。儘可能地,通配符的使用應限制在方法/構造函數參數中。(我想象這個問題的實際代碼是不同的,但只是說...)。 – ColinD

回答

1

我實際上是能夠通過改變

2 Function<?, String> function = new Function<Object, String>() { 

解決這

2 Function<? super Object, String> function = new Function<Object, String>() { 

這是合理的,當你想想 - 功能是這裏的消費者(從臭名昭著的PECS成語)。

+0

請注意'?超級對象「只能是」對象「。 –

+1

...這是非常不同於普通 kutschkem

2

這是因爲Function<?,String>可能是Function<Object,String>,Function<String,String>,Function<Foo,String>中的任何一個。因此,您無法將一個對象輸入到函數中是正確的,因爲它實際上可能需要一個Foo來代替。

當然,因爲你有Iterable<?>,你只知道可迭代吐出對象,所以你只能用Function<Object,WhatEver>來轉換它。

+0

這並不能解釋爲什麼它在build 4中工作。也沒有解釋爲什麼'Function <?擴展Object,String>'也是錯誤的。 – mindas

+0

@mindas顯然是一個微妙的通配符捕獲錯誤,因爲修復。另外,'? extends Object'與我們的目的相同,因此適用相同的推理。 –

+0

@mindas如果它在構建4中工作,那麼我懷疑這實際上是構建4中的一個錯誤。我非常肯定這不應該編譯。 – kutschkem

6

的方法簽名是:

<F,T> Iterable<T> transform(Iterable<F> fromIterable, Function<? super F,? extends T> function) 

,這意味着該類型參數F是什麼:

Iterable<F> : 
    F can be any type here, but will influence the type parameter to Function 
Function<? super F, ? extends T> : 
    the first type parameter (? super F) MUST be a supertype of F 

如果鍵入:

Iterable<?> 
Function<?, String> 

你說的任何東西可迭代,所以它可能是例如Iterable<Integer>。 你也在說從任何東西的功能到字符串,所以它可能是例如Function<String, String>。 由於String不是Integer的超類,因此不符合(? super F)條件。