2015-11-03 4 views
8

Код ниже компилируется отлично, но исключает во время выполнения. Это ожидаемое поведение и почему?LambdaConversionException при использовании метода смешивания и общих данных

Код:

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); } 
} 

Выход:

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 
+0

Я получаю ожидаемый 'java.lang.IllegalStateException: поток уже оперирован или закрыт' с помощью java 1.8.0_60 –

+0

@AlexisC. Странно (по крайней мере, ваш результат имеет больше смысла, чем мой). Я тоже на 1.8.0_60 - Windows x64. – assylias

+0

Что произойдет, если вы прокомментируете первую строку (с минусом), чтобы поток был открыт? –

ответ

1

Это проблема с Netbeans, и я не могу воспроизвести проблему при использовании javac из командной строки. Я подал bug report.

+0

Я не думаю, что это ошибка Netbeans, проверьте мой ответ, это было сообщено как ошибка в complier –

+0

@SleimanJneidi Я не знаю Думаю, это так. Эта ошибка была исправлена ​​в 8u40, и у меня есть проблема с 8u60 + компиляция кода и отлично работает с javac (но не в Netbeans). – assylias

+1

Если вы отключите «скомпилировать при сохранении», проблема исчезнет. Возможно, это отключает компилятор Netbeans и переключается на javac? –

5

Ваш код не будет работать, даже если вы используете лямбды вместо ссылок метод, потому что поток уже исчерпан

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

Потоки - одни. Но давайте оставим это отдельно. Когда вы используете ссылочную версию метода, он фиксирует Number как параметр типа, а не Comparable, где Number не имеет compareToможет быть, потому что Number здесь более конкретный. Если вы просто использовать Comparable будет работать нормально

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 

ИМО (только быть осторожными): Я считаю, что это ошибка.

Что я действительно верю: это определенно ошибка.

Редактировать: Оказалось, что на самом деле это ошибка, и это было исправлено, как подтвердил Брайан Гетц. https://bugs.openjdk.java.net/browse/JDK-8058112. Согласно базе данных об ошибках, это было зафиксировано в 8u40

3

Проблема инициализации сайта вызов адресован через JDK-8058112 имеющихся в JDK 8u40 b17 или более поздней версии.

+0

Ошибка ссылки: https://bugs.openjdk.java.net/browse/JDK-8058112 –

1

Для тех, кто сталкивается с этой проблемой в 2017 году с java8 1.8.0_141, есть еще один зарегистрированный отчет об ошибке JDK-8142476, а исправленная версия - только java9.