【问题标题】:Generic Class Enum Return type泛型类枚举返回类型
【发布时间】:2016-04-20 04:58:31
【问题描述】:

我已经定义了一个转换器接口和几个转换器:

public interface StringConverter<T> {
  T convert(String value);
}

public class EnumConverter<E extends Enum<E>> implements StringConverter<E>{

  private final Class<E> enumClass;

  public EnumConverter(Class<E> enumClass) {
    this.enumClass = enumClass;
  }

  @Override
  public E convert(String value) {
    return Enum.valueOf(enumClass, value);
  }
}

public class IntegerConverter implements StringConverter<Integer> {

  public Integer convert(String value) {
    return Integer.parseInt(value);
  }

}

我创建了一个返回 StringConverter 类的工厂接口。

public interface StringConverterClassFactory {
  <T> Class<? extends StringConverter<T>> getConverter(Class<T> forType);
}

我在使用 StringConverterClassFactory 实现时遇到问题。

public class DefaultConverterClassFactory implements StringConverterClassFactory {

  @Override
  public <T> Class<? extends StringConverter<T>> getConverter(Class<T> forType) {
    if(forType.equals(int.class) || forType.equals(Integer.class))
      return (Class<? extends StringConverter<T>>)IntegerConverter.class;
    else if(forType.isEnum())
      return (Class<? extends StringConverter<T>>)EnumConverter.class;
    else
      return null;
  }
}

导致两个转换器的编译错误,即incompatible types: Class&lt;IntegerConverter&gt; cannot be converted to Class&lt;? extends StringConverter&lt;T&gt;&gt;

使用原始类型我可以摆脱 IntegerConverter 编译错误,但 EnumConverter 仍然出现相同的错误。 error: incompatible types: Class&lt;EnumConverter&gt; cannot be converted to Class&lt;? extends StringConverter&lt;?&gt;&gt;

public class DefaultConverterFactory implements StringConverterClassFactory {

  @Override
  public Class<? extends StringConverter<?>> getConverter(Class forType) {
    if(forType.equals(int.class) || forType.equals(Integer.class))
      return IntegerConverter.class;
    else if(forType.isEnum())
      return (Class<? extends StringConverter<?>>) EnumConverter.class;
    else
      return null;
  }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: java generics enums


    【解决方案1】:

    你可以这样做:

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public <T> Class<? extends StringConverter<T>> getConverter(Class<T> forType) {
        if (forType.equals(int.class) || forType.equals(Integer.class)) {
            return (Class) IntegerConverter.class;
        } else if (forType.isEnum()) {
            return (Class) EnumConverter.class;
        } else {
            return null;
        }
    }
    

    【讨论】:

    • 这行得通。你能解释一下为什么 EnumConverter.class 与 (Class extends StringConverter>>)、(Class extends StringConverter>) 和 (Class extends StringConverter>> 不兼容吗? )?
    • 我在四处寻找类似的东西时发现了这个:stackoverflow.com/questions/1079279/…
    • @BrandonJohnson: EnumConverter.class 的类型为Class&lt;EnumConverter&gt;,它不是Class&lt;? extends StringConverter&lt;?&gt;&gt; 的子类型,因为EnumConverter 不是StringConverter&lt;?&gt; 的子类型。原因是EnumConverter 是泛型类型;使用其原始类型会关闭所有泛型,包括其继承中的泛型。你可以说EnumConverter&lt;?&gt;StringConverter&lt;?&gt;的子类型,或者EnumConverterStringConverter的子类型,但不能说EnumConverterStringConverter&lt;?&gt;的子类型。
    【解决方案2】:

    &lt;T&gt;&lt;?&gt; 都是冗余的!

    就这样写吧:

        @Override
        public Class<? extends StringConverter> getConverter(Class forType) {
            if (forType.equals(int.class) || forType.equals(Integer.class)) {
                return IntegerConverter.class;
            } else if (forType.isEnum()) {
                return EnumConverter.class;
            } else {
                return null;
            }
        }
    


    编辑:
    我以前没有见过这个问题,所以我真的不知道原因。这是我的猜测:

    • &lt;T&gt; 不是实际的 Type,所以只要转换为 Class&lt;? extends StringConverter&lt;T&gt;&gt; 就会出错,比如 Class&lt;IntegerConverter&gt; cannot be converted to Class&lt;? extends StringConverter&lt;T&gt;&gt;
    • IntegerConverter 使用实际类型 &lt;Integer&gt; 实现,因此 (Class&lt;? extends StringConverter&lt;Integer&gt;&gt;) IntegerConverter.class 将是正确的,(Class&lt;? extends StringConverter&lt;?&gt;&gt;) IntegerConverter.class 也有效。
    • EnumConverter 使用泛型类型&lt;E extend Enum&lt;E&gt;&gt; 实现,因此EnumConverter.class 不能转换为具有以下类型的任何形式:Class&lt;? extends StringConverter&lt;T&gt;&gt;Class&lt;? extends StringConverter&lt;?&gt;&gt;

      证明:
      进行另一个实现:

      public class GenericConverter<E> implements StringConverter<E> { public E convert(String value) { return null; } }

      (Class&lt;? extends StringConverter&lt;T&gt;&gt;) GenericConverter.class(Class&lt;? extends StringConverter&lt;?&gt;&gt;) GenericConverter.class 都不正确。

    【讨论】:

    • 这会导致 IntegerConverter 和 EnumConverter 的编译错误。
    • @BrandonJohnson 编辑你的超级界面Class&lt;? extends StringConverter&gt; getConverter(Class forType);。如果您无法编辑界面,请尝试@Teemu Ilmonen 的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多