泛型类 枚举 返回类型

3

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

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;
  }
}

两个转换器都会导致编译错误,即不兼容类型:Class <IntegerConverter>无法转换为Class<? extends StringConverter<T>>

使用原始类型可以解决IntegerConverter的编译错误,但对于EnumConverter仍然出现相同的错误。错误:不兼容的类型:Class<EnumConverter>无法转换为Class<? extends StringConverter<?>>

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;
  }
}

非常感谢您的帮助。

2个回答

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 <T >>),以及(Class <? extends StringConverter <T extends Enum <T >>>)不兼容吗? - Brandon Johnson
我在寻找类似的东西时发现了这个网址:https://dev59.com/-XNA5IYBdhLWcg3wIqLr - Teemu Ilmonen
1
@BrandonJohnson: EnumConverter.class的类型是Class<EnumConverter>,它不是Class<? extends StringConverter<?>>的子类型,因为EnumConverter不是StringConverter<?>的子类型。原因是EnumConverter是一个泛型类型;使用其原始类型会关闭所有泛型,包括其继承中的泛型。你可以说EnumConverter<?>StringConverter<?>的子类型,或者EnumConverterStringConverter的子类型,但不能说EnumConverterStringConverter<?>的子类型。 - newacct

0

<T><?>都是多余的!

只需这样写:

    @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;
        }
    }


编辑:
我以前没有遇到过这个问题,所以我不太清楚原因。以下是我的猜测:

  • <T> 不是一个真正的类型,所以只要将其转换为 Class<? extends StringConverter<T>>,就会出现错误,例如Class<IntegerConverter> 无法转换为 Class<? extends StringConverter<T>>
  • IntegerConverter 实现了实际类型 <Integer>,因此 (Class<? extends StringConverter<Integer>>) IntegerConverter.class 正确,而 (Class<? extends StringConverter<?>>) IntegerConverter.class 也可以使用。
  • EnumConverter 使用泛型类型 <E extend Enum<E>> 实现,因此 EnumConverter.class 不能转换为任何形式的类型:Class<? extends StringConverter<T>>Class<? extends StringConverter<?>>

    证明如下:
    添加另一种实现方式:

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

    (Class<? extends StringConverter<T>>) GenericConverter.class(Class<? extends StringConverter<?>>) GenericConverter.class 都是不正确的。


这会导致 IntegerConverter 和 EnumConverter 都出现编译错误。 - Brandon Johnson
@BrandonJohnson 编辑您的超级接口 Class<? extends StringConverter> getConverter(Class forType);。如果您无法编辑该接口,请尝试 @Teemu Ilmonen 的答案。 - magooup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接