Enumerations and common methods in java

I still have problems with some corner cases in the java generics system.

I have this method (I'm only interested in the signature):

 interface Extractor<RETURN_TYPE> {
    public <U extends Enum<U>> RETURN_TYPE extractEnum(final Class<U> enumType);
}

(think of an interface whose implementation sometimes extracts EnumSet, sometimes the executable extracts JComboBox, etc.)

and I want to call it a class obtained at runtime, so I just call it like this:

 public static <RETURN_TYPE> RETURN_TYPE extractField(final Extractor<RETURN_TYPE> extractor, final Field field) {
    final Class<?> type = field.getType();
    if (type.isEnum())
        return extractor.extractEnum(/* error here*/type.asSubclass(Enum.class));
    throw new RuntimeException("the rest of the visitor is not necessary here");
}

and I get a strange error message: incompatible types found: java.lang.Object required: RETURN_TYPE

location of the message, if immediately after the opening of the call reject, up to the "t" type.

if I call it from a non-general context, it works:

    Integer extractField(final Extractor<Integer> extractor, final Field field) {
        final Class<?> type = field.getType();
        if (type.isEnum())
            return extractor.extractEnum(type.asSubclass(Enum.class));
        throw new RuntimeException("the rest of the visitor is not necessary here");
    }

Does anyone have an explanation and solution to this problem?

Here is the complete file for people who want to play with it:

public class Blah {
    interface Extractor<RETURN_TYPE> {
        public <U extends Enum<U>> RETURN_TYPE extractEnum(final Class<U> enumType);
    }

    public static <RETURN_TYPE> RETURN_TYPE extractField(final Extractor<RETURN_TYPE> extractor, final Field field) {
        final Class<?> type = field.getType();
        if (type.isEnum())
            return extractor.extractEnum(/* error here*/type.asSubclass(Enum.class));
        throw new RuntimeException("the rest of the visitor is not necessary here");
    }

    public static Integer extractField(final Extractor<Integer> extractor, final Field field) {
        final Class<?> type = field.getType();
        if (type.isEnum())
            return extractor.extractEnum(type.asSubclass(Enum.class));
        throw new RuntimeException("the rest of the visitor is not necessary here");
    }
}

thanks in advance,

Niko

+3
3

, . (, , , "" ), javac (, IDE).

, , , , , extractor.extractEnum Object, RETURN_TYPE. , enum... , Extractor Extractor<RETURN_TYPE>, return extractor.extractEnum(...);.

, null ( , enum ), . , , , Extractor U<RETURN_TYPE>, .

, , . , extractEnum RETURN_TYPE? : , : , U<RETURN_TYPE> RETURN_TYPE - eep...

1.6, Sun, javac. , :

public class Test {
  interface Sub<O> {
    public <I extends Enum<I>> O method(final Class<I> enumType);
  }

  public static <O> O go(final Sub<O> sub) {
    return sub.method(null);
  }
}

P.S. , . " , ", , , Extractor. (, , .)

+3

.

, Extractor.extract U, Enum T, ? VV T U? U VV, Class<VV>, Class<Enum>. , , , Class<VV>

class Outer {
  static class Extractor<T> {
    public <U extends Enum<U>> T extract(final Class<U> lala) {
      return null;
    }
    // two type parameters, T and U
    // U must be an enum
    // T is arbitrary class
  }

  static <VV extends Enum<VV>> VV extract(final Extractor<VV> extractor, Class<VV> vvClass) {
    final Class<?> type = null;
    return extractor.extract(vvClass);
    // Outer.extract returns VV 
    // T -> VV
    // it seems VV is also U
  }
}
+2

, Field.getType( ) . , "unchecked", ALL .

, :

interface Extractor {
    public Object extractEnum( final Class enumType );
}

, , extractEnum java.lang.Object, . , .

.

@SuppressWarnings( "unchecked" )
public static <RETURN_TYPE> RETURN_TYPE extractField(
       final Extractor<RETURN_TYPE> extractor,
       final Field field
    )
{
    final Class type = field.getType(); // unchecked

    if (type.isEnum())
    {
        // needs cast
        return (RETURN_TYPE) extractor.extractEnum( type ); // unchecked
    }
    throw new RuntimeException("the rest of the visitor is not necessary here");
}

REFUSE THIS COMMENT: To answer the original question about why you have a compilation error. This is a square snap to a round hole problem. type.asSubclass( Enum.class )returns Class< ? extends Enum >, it still does not match the Class< U >one that expects the interface call.

+1
source

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


All Articles