Why does a local variable affect type equality inference constraints?

I have a problem with understanding capture in type inference. I have a code that looks like this:

import java.util.EnumSet;

class A {
    static enum E1 {
    X
    }

    private static <T extends Enum<T>> EnumSet<T> barEnum(Class<T> x) {
        return null;
    }

    private static void foo1(EnumSet<E1> s, E1 e) {
        EnumSet<E1> x2 = barEnum(e.getClass());
    }

    private static void foo2(EnumSet<E1> s) {
        EnumSet<E1> x = barEnum(s.iterator().next().getClass());
    }
}

This gives two compilation errors:

Test.java:15: error: method barEnum in class A cannot be applied to given types;
        EnumSet<E1> x2 = barEnum(e.getClass());
                         ^
  required: Class<T>
  found: Class<CAP#1>
  reason: inference variable T has incompatible equality constraints E1,CAP#2
  where T is a type-variable:
    T extends Enum<T> declared in method <T>barEnum(Class<T>)
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends E1 from capture of ? extends E1
    CAP#2 extends E1 from capture of ? extends E1
Test.java:19: error: method barEnum in class A cannot be applied to given types;
        EnumSet<E1> x = barEnum(s.iterator().next().getClass());
                        ^
  required: Class<T>
  found: Class<CAP#1>
  reason: inference variable T has incompatible equality constraints E1,CAP#2
  where T is a type-variable:
    T extends Enum<T> declared in method <T>barEnum(Class<T>)
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends E1 from capture of ? extends E1
    CAP#2 extends E1 from capture of ? extends E1
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors

When trying to understand the error, I changed foo2to get the value getClass()in a local variable to see the actual type:

private static void foo2(EnumSet<E1> s) {
    // this works
    Class<? extends Enum> c = s.iterator().next().getClass();
    EnumSet<E1> y = barEnum(c);
}

Now the error has disappeared and the code has been compiled. I don’t understand how introducing a local variable with the same type as the expression changes the type inference algorithm and solves the problem.

+4
source share
2 answers

When you assign a s.iterator().next().getClass()local variable, you use the raw type - Enum. This is how you get a compilation error, but get a warning.

, :

private static void foo2(EnumSet<E1> s) {
    EnumSet<E1> x = barEnum((Class<? extends Enum>)s.iterator().next().getClass());
}

:

private static void foo2(EnumSet<E1> s) {
    EnumSet<E1> x = barEnum(s.iterator().next().getDeclaringClass());
}
+1

T E1, T - enum E1. ( , . .)

, , E1 enum:

private static <E1 extends Enum<E1>> void foo1(EnumSet<E1> s, E1 e) {
-1

Source: https://habr.com/ru/post/1692962/


All Articles