java8 泛型 null 报错,使用java 8中的泛型类型错误,而不是java 7

I have a piece of code which compiles fine under java 7, but not under java 8. Here is a self-contained reproducing example (I've taken real code that exhibits this problem and stubbed out all the implementations):

import java.util.Iterator;

class ASTNode implements Iterable {

@Override public Iterator iterator() { return null; }

}

class List extends ASTNode {}

interface Function {}

class Iterables {

public static Iterable transform(

Iterable fromIterable, Function super F, ? extends T> function) { return null; }

}

class AstFunctions {

public static > Function prettyPrint() { return null; }

}

public class Main {

public static void test() {

List extends ASTNode>> list = null;

Iterables.transform(list, AstFunctions.prettyPrint());

}

}

Witness:

$ javac -version

javac 1.8.0_05

$ javac -source 1.7 Main.java

warning: [options] bootstrap class path not set in conjunction with -source 1.7

1 warning

$ javac -source 1.8 Main.java

Main.java:23: error: method transform in class Iterables cannot be applied to given types;

Iterables.transform(list, AstFunctions.prettyPrint());

^

required: Iterable,Function super F,? extends T#1>

found: List,Function,String>

reason: cannot infer type-variable(s) F,T#1,T#2

(argument mismatch; Function cannot be converted to Function super CAP#1,? extends String>)

where F,T#1,T#2 are type-variables:

F extends Object declared in method transform(Iterable,Function super F,? extends T#1>)

T#1 extends Object declared in method transform(Iterable,Function super F,? extends T#1>)

T#2 extends ASTNode> declared in method prettyPrint()

where CAP#1 is a fresh type-variable:

CAP#1 extends ASTNode> from capture of ? extends ASTNode>

1 error

(Perhaps notable is that Eclipse, configured for 1.8 compatibility, has no issues with this code).

Is this a compiler bug? If not, then assuming I'm allowed to change AstFunctions and Main (but not ASTNode, List, Function, or Iterables), how can I make this code compile? I'd also like to understand, if possible, what change to Java 8's type system makes this code not compile.

解决方案

UPDATE: see other answer - this was a bug in javac which has been fixed.

It feels like this should not compile and that Java 8 is exhibiting the correct behaviour:

Iterables.transform expects an Iterable fromIterable and Function super F..., so the first generic type of Function needs to be a super class of the generic type of the Iterable

in your main, the type of the Iterable is F1 == ? extends ASTNode> and the first type of the Function returned by prettyPrint is F2 == T extends ASTNode>

I don't think there is a way to prove that F2 is a supertype of F1. For example let's say you have:

class A1 extends ASTNode {}

class A2 extends ASTNode {}

and in your main:

List extends ASTNode>> list = new List(); //F1 = A1

You could imagine that prettyPrint returns a Function (i.e. F2 = A2) and A2 is not a super class of A1.

So I believe the compile error makes sense. But I won't try to prove it based on the specifications because that would eat most of my day!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值