Here's sample code that fails to compile in Java 8 (1.8.0_40) but compiles in Eclipse 4.4 JDT standalone compiler (Bundle-Version: 3.10.0.v20140604-1726) and runs successfully:
import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Test method references to local class constructors.
*/
public class LocalClassTest {
public long sumOfLengths(String[] input) {
class Sum {
final long value;
Sum(long value) {
this.value = value;
}
Sum(Sum left, Sum right) {
this.value = left.value + right.value;
}
Sum add(String s) {
return new Sum(value + s.length());
}
}
return Arrays.stream(input)
.reduce(new Sum(0), Sum::add, Sum::new)
.value;
}
static String[] input =
{
"a", "ab", "abc"
};
@Test
public void localClassConstructorMethodRefs() {
assertEquals(sumOfLengths(input), 6);
}
}
javac
spits out the following error message:
Error:(32, 25) java: incompatible types: cannot infer type-variable(s) U
(argument mismatch; invalid constructor reference
cannot access constructor Sum(Sum,Sum)
an enclosing instance of type LocalClassTest is not in scope)
Reading through JLS 15.9.2 (Determining Enclosing Instances) and 15.13.3 (Run-Time Evaluation of Method References), I can't see why this should fail to compile, and the error message seems outright false since I can manually construct a Sum
instance in the same method just fine.
I've found a previous question Constructor reference for inner class fails with VerifyError at runtime that seems relevant, and the linked JDK issue there (https://bugs.openjdk.java.net/browse/JDK-8037404) indicate a series of compiler issues in this area; maybe this is another instance of a more general problem. Nevertheless, I'm not sure I'm reading the spec right; could this work in another way?