erased.java,为什么在Java 8中有一个未经检查的方法参数转换时,返回类型的泛型会被擦除?...

Consider the following code sample:

import java.util.ArrayList;

import java.util.List;

public class Main {

public static void main(String[] args) {

List list = new ArrayList();

String response = getProducer(list).get();

}

static Producer getProducer(List list) {

return new Producer();

}

}

class Producer {

T get() {

return null;

}

}

When compiled in Java 7 it just produces an expected warning for getProducer(list):

Warning:(7, 39) java: unchecked conversion

required: java.util.List

found: java.util.List

However, when compiled in Java 8 it produces the following error for the response = getProducer(list).get() assignment:

Error:(7, 48) java: incompatible types: java.lang.Object cannot be converted to java.lang.String

So apparently the type returned from getProducer(list) is not Producer, but erased Producer (which is also confirmed by means of the 'extract variable' feature in the IDE). This is very puzzling because getProducer method always returns Producer.

Oddly enough it could be fixed by avoiding unchecked conversion while calling getProducer method, either by:

Change parameter type of getProducer from List to List

Change type of list variable from List to List

Updates

Java used is Oracle JDK 1.8.0_40

I have also tried using source and target options from 1.5 through 1.7 with the Java 8 compiler and the result was the same.

Questions

How could the generic type of the passed argument affect a generic type of the method return value while the generic type of the return value is fixed in the method signature?

Why is there such a backward-incompatible change in behavior between Java 7 and Java 8?

解决方案

This looks like a known compatibility issue reported here and here.

From the second link:

The following code which compiled, with warnings, in JDK 7 will not

compile in JDK 8:

import java.util.List;

class SampleClass {

static class Baz {

public static List> sampleMethod(Baz param) {

return null;

}

}

private static void bar(Baz arg) {

Baz element = Baz.sampleMethod(arg).get(0);

}

}

Compiling this code in JDK 8 produces the following error:

SampleClass.java:12: error:incompatible types: Object cannot be

converted to Baz

Baz element = Baz.sampleMethod(arg).get(0);

Note: SampleClass.java uses unchecked or unsafe operations. Note:

Recompile with -Xlint:unchecked for details. 1 error

Deriving from this, the OP's code can be fixed by replacing this line (the type declartion on the right hand side threw me off - I read it as a typed array list which it is not):

List list = new ArrayList();

with

List list = new ArrayList();

which will not result in type being being erased from return type of method getProducer(List list)

Quote from second link again:

In this example, a raw type is being passed to the

sampleMethod(Baz) method which is applicable by subtyping (see

the JLS, Java SE 7 Edition, section 15.12.2.2). An unchecked

conversion is necessary for the method to be applicable, so its return

type is erased (see the JLS, Java SE 7 Edition, section 15.12.2.6). In

this case the return type of sampleMethod(Baz) is

java.util.List instead of java.util.List> and thus the

return type of get(int) is Object, which is not assignment-compatible

with Baz.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值