9

The code below compiles fine but throws an exception at runtime. Is this the expected behaviour and why?

Code:

public static void main(String[] args) {
  A<Integer> a = new A<> ();
  System.out.println(a.min()); //prints null as expected
  System.out.println(a.max()); //throws exception
}

static class A<T extends Number & Comparable<? super T>> {
  Stream<T> s = Stream.empty();
  public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
  public T max() { return s.max(T::compareTo).orElse(null); }
}

Output:

null
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
    at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
    at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
    at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
    at abc$A.max(abc.java:19)
    at abc.main(abc.java:8)
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Number; not a subtype of implementation type interface java.lang.Comparable
    at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
    at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
    at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
    ... 4 more
20
  • 1
    Hmm, JDK 1.8.0_60 Windows 10 x64, I get the same behaviour as the OP, i.e. LambdaConversionException is thrown... I do have IllegalStateException if I change max argument to (t1, t2) -> t1.compareTo(t2) instead of T::compareTo. Commented Nov 3, 2015 at 19:47
  • 1
    This looks similar but I can reproduce that one even with javac 1.8.0_60, which I cannot do with the example in this case. Commented Nov 3, 2015 at 20:28
  • 2
    Of course, you could just use Comparator.naturalOrder() instead of T::compareTo but it’s a pity that there are still problems with multiple bounds… Commented Nov 3, 2015 at 20:38
  • 1
    @SkinnyJ: I can still reproduce the problem of that question with jdk1.8.0_60 Commented Nov 3, 2015 at 20:48
  • 2
    Keep in mind that the compiler is involved. When using an older compiler, like the one integrated into Netbeans, you get the problem, even if the runtime is uptodate. Commented Nov 3, 2015 at 21:01

4 Answers 4

6

Your code wouldn't work even if you use lambdas instead of method references because the stream is already exhausted

 System.out.println(a.min()); 
 System.out.println(a.max()); // exhausted

Streams are one off. But lets leave this apart. When you use the method reference version, it is capturing Number as a type parameter and not Comparable where Number has no compareTo maybe because Number is more specific here. If you just use Comparable it will work fine

  static class A<T extends Comparable<? super T>> {
    Stream<T> s = Stream.empty();
    public T min() { return s.min((t1, t2) -> t1.compareTo(t2)).orElse(null); }
    public T max() {
        T t = s.max(T::compareTo).orElse(null);
        return t; }
 }

System.out.println(a.max()); //null

IMO (just to be cautious) : I believe it is a bug.

What I actually believe: It is definitely a bug.

Edit: It turns out that this was actually a bug and it was fixed as confirmed by Brian Goetz. https://bugs.openjdk.java.net/browse/JDK-8058112. According to the bug database, this was fixed in 8u40

Sign up to request clarification or add additional context in comments.

Comments

4

The call site initialization problem is addressed through JDK-8058112 available in JDK 8u40 b17 or later.

Comments

3

For those who are facing this issue in 2017 with java8 1.8.0_141, there's another filed bug report JDK-8142476 and the fix version is java9 only.

Comments

2

It seems to be a Netbeans issue and I can't reproduce the problem when using javac from the command line. I have filed a bug report.

3 Comments

I don't think it is Netbeans fault, check my answer, it was reported as a bug in the complier
@SleimanJneidi I don't think that's the case. That bug was fixed in 8u40 and I have the problem with 8u60 + the code compiles and runs fine with javac (but not in Netbeans).
If you turn off "compile on save", the problem disappears. Perhaps that turns off the Netbeans compiler and switches to javac?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.