FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Return type is not inferred from target type when there is more than one return statement in the lambda expression, the compiler instead tries to compare different return values to infer the return type.
Take as example the following code ( taken from http://stackoverflow.com/questions/29956936/is-this-esoteric-generics-error-a-compiler-bug-or-a-new-restriction-inferred-t?nah=29957168#29957168 ) this code fails to compile:
import java.sql.Connection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class CompilerIssue
{
public Set<String> test(int value)
{
return perform(connection -> {
if (value % 2 == 0)
{
return Collections.<String>emptySet();
}
else
{
return new HashSet<>(10);
}
});
}
<V> V perform(BusinessLogic<V> logic)
{
return null;
}
interface BusinessLogic<V>
{
V execute(Connection connection) throws Exception;
}
}
The problem is in the line "return new HashSet<>(10);", it doesn't infer the type String but the type Object. However, if the other return statement is commented out and replaced with a "return null;" then teh code compiles fine.
REGRESSION. Last worked in version 8u5
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Copy the following code in a file "CompileIssue.java" and compile it ( javac CompileIssue.java )
------ File start ------
import java.sql.Connection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class CompilerIssue
{
public Set<String> test(int value)
{
return perform(connection -> {
if (value % 2 == 0)
{
return Collections.<String>emptySet();
}
else
{
return new HashSet<>(10);
}
});
}
<V> V perform(BusinessLogic<V> logic)
{
return null;
}
interface BusinessLogic<V>
{
V execute(Connection connection) throws Exception;
}
}
------ file end ------
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code should compile without errors, the same way as in jdk1.8.0_05
ACTUAL -
Compiler generates the following error:
Error:(12, 23) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: java.util.Set<? extends java.lang.Object>
upper bound(s): java.util.Set<java.lang.String>,java.lang.Object
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.sql.Connection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class CompilerIssue
{
public Set<String> test(int value)
{
return perform(connection -> {
if (value % 2 == 0)
{
return Collections.<String>emptySet();
}
else
{
return new HashSet<>(10);
}
});
}
<V> V perform(BusinessLogic<V> logic)
{
return null;
}
interface BusinessLogic<V>
{
V execute(Connection connection) throws Exception;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Specifying explicitly the type ("return new HashSet<String>(10);" instead of "return new HashSet<>(10);")