// VIM_TEST_SETUP let g:java_highlight_functions = 'style' // VIM_TEST_SETUP let g:java_highlight_generics = 1 import java.lang.invoke.MethodHandle; import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.IntSupplier; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.ToIntFunction; import java.util.function.UnaryOperator; class MethodReferencesTests { static { // Primary :: [TypeArguments] Identifier try { Runnable r1 = ((Runtime) null)::gc; } catch (NullPointerException expected) { } Supplier s1 = ((Number) 0)::hashCode; Supplier s2 = ((Comparable) '\0')::hashCode; Supplier s3 = ((Comparable) false)::hashCode; Supplier s4 = "::"::hashCode; Supplier> s5 = int[].class::arrayType; Supplier s6 = new MethodReferencesTests() :: hashCode; Supplier s7 = ((Number) (new MethodReferencesTests().xy)[0])::intValue; Supplier s8 = new MethodReferencesTests().xy:: clone; Consumer c1 = System.out :: println; Supplier s9 = ((Supplier) ()->"()").get() ::getBytes; Supplier sa = ((Supplier) ((Supplier) ((Supplier) ((Supplier) ((Supplier) () -> "() -> ()") ::toString) ::toString) ::get) ::toString) ::toString; // ExpressionName :: [TypeArguments] Identifier // ReferenceType :: [TypeArguments] Identifier Function f1 = s -> s :: length; Function> f2 = ii -> ((int[]) (ii.length > 0 ? ii[0] : ii)) :: clone; UnaryOperator uo1 = String::valueOf; ToIntFunction tif1 = s -> s.transform( String :: length); // ClassType :: [TypeArguments] new // ArrayType :: new Function f3 = C2::new; Function f4 = pci -> pci.new C21(null); // Cf. "d". Supplier> sb = C1::new; Function> f5 = C1 :: new; IntFunction[]> if1 = C1[] :: new; IntFunction if2 = byte[] :: new; } final int[] xy = { 0, 1 }; // super :: [TypeArguments] Identifier // TypeName . super :: [TypeArguments] Identifier MethodReferencesTests() { Predicate p1 = MethodReferencesTests.super::equals; Predicate p2 = MethodReferencesTests.this::equals; } interface I4 extends I3 { default Predicate superEqualist() { return I3 .super::equals; /* "a" */ } } interface I3 extends I2 { default Predicate superEqualist() { return I2. super::equals; /* "b" */ } } interface I2 extends I1 { default Predicate superEqualist() { /* Non-capturing gymnastics for super::equals. */ return Function.>> identity() .apply(mh -> o -> MethodReferencesTests .invokePredicate(mh, o)) .apply(EQUALS.bindTo(this)); } } interface I1 { default Predicate equalist() { /* Non-capturing gymnastics for this::equals. */ return Function., Predicate>> identity() .apply(that -> o -> Function ., T>> identity() .apply(I1:: /* "c" */ equals) .test(that, o)) .apply(I1.this); } } static boolean invokePredicate(MethodHandle mh, T o) { try { return (boolean) mh.invokeExact(o); } catch (Throwable th) { throw new RuntimeException(th); } } private static final MethodHandle EQUALS; static { try { EQUALS = java.lang.invoke.MethodHandles.lookup() .findSpecial( I1.class, "equals", java.lang.invoke.MethodType.methodType( boolean.class, Object.class), I2.class); } catch (ReflectiveOperationException e) { throw new Error(e); } } static class C1 { C1() { } C1(A dummy) { } } static class C2 { C2() { this(""); } C2(A dummy) { C2.stringer().apply(((Function) C2.C21::new) /* "d" */ .apply(C2.this)); } class C21 { C21() { this(""); } C21(B dummy) { C2.stringer().apply(C2.this); } } static Function stringer() { return T::toString; /* "e" */ } } }