2013-01-21 68 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)条件。