ADDITIONAL SYSTEM INFORMATION :
javac 15-ea build 21
A DESCRIPTION OF THE PROBLEM :
When a method accepting a functional interfarce gets a generic method reference, the type inference may not work correctly.
In the following example, the first examples do not compile, producing "error: no suitable method found for thenComparing(Comparator<T#1>)". Please note, that using a non-generic method reference, as explicitly specifying the type, works.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the attached snippet.
---------- BEGIN SOURCE ----------
import java.util.Map;
import java.util.Comparator;
public class Foo {
private static final Map<String, Integer> FREQUENCES = Map.of("a", 2, "b", 3);
public static void test() {
// Failing:
// 1a: When chained
Comparator<String> c1 = Comparator.comparingInt(FREQUENCES::get)
.thenComparing(Comparator.naturalOrder()); // <- 'error: no suitable method found for thenComparing(Comparator<T#1>)'
// 1b: With LVTI
var compByFreqAsc = Comparator.comparingInt(FREQUENCES::get);
Comparator<String> c2 = compByFreqAsc.thenComparing(Comparator.naturalOrder()); // <- 'error: no suitable method found for thenComparing(Comparator<T#1>)'
// Compiling:
// 2a: With non-generic method reference
Comparator<String> c5 = Comparator.comparingInt(Foo::frequency)
.thenComparing(Comparator.naturalOrder());
// 2b: With lambda parameter type declaration
Comparator<String> c3 = Comparator.comparingInt((String s) -> FREQUENCES.get(s))
.thenComparing(Comparator.naturalOrder());
// 2c: With generic method explicit type parameter declaration
Comparator<String> c4 = Comparator.<String>comparingInt(FREQUENCES::get)
.thenComparing(Comparator.naturalOrder());
// 2d: With intermediate variable
Comparator<String> compByFreqAsc2 = Comparator.comparingInt(FREQUENCES::get);
Comparator<String> c6 = compByFreqAsc2.thenComparing(Comparator.naturalOrder());
}
private static int frequency(String s) {
return FREQUENCES.get(s);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The workarounds (also shown in the code):
- Use non-generic method reference, if possible (2a)
- Replace with a lambda, *and* specify the parameter type (2b)
- Specify the generic method type (2c)
- Use an intermediate variable with explicit type declaration (2d)
FREQUENCY : always
javac 15-ea build 21
A DESCRIPTION OF THE PROBLEM :
When a method accepting a functional interfarce gets a generic method reference, the type inference may not work correctly.
In the following example, the first examples do not compile, producing "error: no suitable method found for thenComparing(Comparator<T#1>)". Please note, that using a non-generic method reference, as explicitly specifying the type, works.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the attached snippet.
---------- BEGIN SOURCE ----------
import java.util.Map;
import java.util.Comparator;
public class Foo {
private static final Map<String, Integer> FREQUENCES = Map.of("a", 2, "b", 3);
public static void test() {
// Failing:
// 1a: When chained
Comparator<String> c1 = Comparator.comparingInt(FREQUENCES::get)
.thenComparing(Comparator.naturalOrder()); // <- 'error: no suitable method found for thenComparing(Comparator<T#1>)'
// 1b: With LVTI
var compByFreqAsc = Comparator.comparingInt(FREQUENCES::get);
Comparator<String> c2 = compByFreqAsc.thenComparing(Comparator.naturalOrder()); // <- 'error: no suitable method found for thenComparing(Comparator<T#1>)'
// Compiling:
// 2a: With non-generic method reference
Comparator<String> c5 = Comparator.comparingInt(Foo::frequency)
.thenComparing(Comparator.naturalOrder());
// 2b: With lambda parameter type declaration
Comparator<String> c3 = Comparator.comparingInt((String s) -> FREQUENCES.get(s))
.thenComparing(Comparator.naturalOrder());
// 2c: With generic method explicit type parameter declaration
Comparator<String> c4 = Comparator.<String>comparingInt(FREQUENCES::get)
.thenComparing(Comparator.naturalOrder());
// 2d: With intermediate variable
Comparator<String> compByFreqAsc2 = Comparator.comparingInt(FREQUENCES::get);
Comparator<String> c6 = compByFreqAsc2.thenComparing(Comparator.naturalOrder());
}
private static int frequency(String s) {
return FREQUENCES.get(s);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The workarounds (also shown in the code):
- Use non-generic method reference, if possible (2a)
- Replace with a lambda, *and* specify the parameter type (2b)
- Specify the generic method type (2c)
- Use an intermediate variable with explicit type declaration (2d)
FREQUENCY : always
- relates to
-
JDK-8141613 Compiler fails to infer generic type
-
- Closed
-