使用泛型来替换特定的类类型

时间:2018-02-23 03:15:26

标签: java generics type-conversion

目前,我有三个类AppleGrapeBanana,我为每个类创建了一个转换器类(可以将字符串转换为列表)。然后我意识到所有这些转换器类基本相同,只是它们采用不同的类类型。 AppleConverter.java

的示例
  public class AppleConverter extends StrutsTypeConverter {

  @SuppressWarnings("rawtypes")
  @Override
  public Object convertFromString(Map context, String[] values, Class toClass) {

    final List<Apple> appleList = new ArrayList<>();
    try {
      for (String appleString : values) {
          Apple apple = Apple.valueOf(appleString);
          appleList.add(apple);
      }
    }
    catch (IllegalArgumentException e) {
      throw new TypeConversionException(e);
    }
    return appleList;
  }

  @SuppressWarnings("rawtypes")
  @Override
  public String convertToString(Map context, Object o) {
    if (o == null) {
      return null;
    }
    if (o instanceof List<?>) {
      List<Apple> list = (List<Apple>) o;
      String appleString = list
        .stream()
        .map(e -> String.valueOf(e))
        .collect(Collectors.joining(","));
      return appleString;
    }
    throw new TypeConversionException("wrong");
  }

基本上,GrapdeConverter.javaBananaConverter.javaAppleConverter.java相同,只是它们采用不同的类类型。 所以我尝试创建一个泛型类,然后那些转换器类可以继承它 我的通用类代码:

    public class FruitConverter<T> extends StrutsTypeConverter {


  @SuppressWarnings("rawtypes")
  @Override
  public Object convertFromString(Map context, String[] values, Class toClass) {
    if (ArrayUtils.isEmpty(values)) {
      return null;
    }
    final List<T> objs = new ArrayList<>();
    try {
      for (String objStr : values) {

           Object obj = toClass.getDeclaredMethod("valueOf", String.class).invoke(null, objStr);

          objs.add(obj);
        }
      }
    }
    catch (IllegalArgumentException e) {
      throw new TypeConversionException(e);
    }
    return objs;
  }

  @SuppressWarnings("rawtypes")
  @Override
  public String convertToString(Map context, Object o) {
    if (o == null) {
      return null;
    }
    if (o instanceof List<?>) {
      List<?> list = (List<?>) o;
      String fruitString = list
        .stream()
        .map(e -> String.valueOf(e))
        .collect(Collectors.joining(","));
      return fruitString;
    }
    throw new TypeConversionException("object is not a list of objs");
  }
}

当我拨打T obj = T.valueOf(objStr);时,会抛出错误can not resolve method valueOf。 在这种情况下,任何人都可以告诉我如何正确应用泛型。

2 个答案:

答案 0 :(得分:1)

你不能在这些表达中使用T,我怀疑你甚至需要泛型来完成这项任务。

快速而肮脏的推广方法是使用反射,而不是T obj = T.valueOf(objStr);使用此:

Object obj = toClass.getDeclaredMethod("valueOf", String.class).invoke(null, objStr);

然后你就可以对所有这样的对象使用相同的功能了。

另一种方法是使用结构,但它需要更多的代码。

答案 1 :(得分:1)

发生编译错误是因为Java的泛型是用type erasure实现的。在这种情况下,T.valueOf被视为与您尝试Object.valueOf时相同,即它不知道要搜索valueOf方法的哪些类,除了Object

您可以使用方法引用将该方法作为函数传递,如以下示例所示:

import java.util.function.Function;

class FruitConverter<T> {
    private final Function<String, T> valueOf;

    FruitConverter(Function<String, T> valueOf) {
        this.valueOf = valueOf;
    }

    // ...
}

class AppleConverter extends FruitConverter<Apple> {
    AppleConverter() {
        super(Apple::valueOf);
    }
}

然后,当您想要调用方法时,可以使用this.valueOf.apply(...)

另见https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html