Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDK8 type inference issue

I'm trying to run the following code which is compiled fine under JDK8 thanks to type inference:

public static <A,B> B convert(A a) {
  return (B) new CB();
}
public static void main(String[] args) {
  CA a = new CA();
  CB b = convert(a); //this runs fine
  List<CB> bl = Arrays.asList(b); //this also runs fine
  List<CB> bl1 = Arrays.asList(convert(a)); //ClassCastException here
}

However, running this throws ClassCastException: CB cannot be cast to [Ljava.lang.Object, but the CB b = convert(a) works fine.

Any idea why?

like image 762
Dan L. Avatar asked Aug 18 '16 15:08

Dan L.


People also ask

What is Java type inference?

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.

Does Java 7 support type inference?

Java SE 7 supports limited type inference for generic instance creation; you can only use type inference if the parameterized type of the constructor is obvious from the context. For example, the following example does not compile: List<String> list = new ArrayList<>(); list.

What is inference in programming?

Type inference is the compile-time process of reconstructing missing type information in a program based on the usage of its variables. ML and Haskell are two languages where this aspect of compilation has enjoyed some popularity, allowing type information to be omitted while static type checking is still performed.


1 Answers

Whenever you create a generic method with a signature that promises to return whatever the caller wishes, you are asking for trouble. You should have got an “unchecked” warning from the compiler which basically means: unexpected ClassCastExceptions may occur.

You expect the compiler to infer

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB>convert(a));

whereas the compiler actually inferred

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB[]>convert(a));

as far as I know, because it prefers method invocations not requiring a varargs packaging (which is compatible with pre-varargs code).

This fails because your convert method does not return the expected array type.

like image 172
Holger Avatar answered Oct 16 '22 03:10

Holger