Java - 通用抽象类的通用列表

时间:2014-11-10 09:53:04

标签: java generics

我正在使用包含抽象通用Parsable类的库:

public abstract class Parsable<T> {
  T parse(String s);
}

通过继承此类,允许用户从字符串创建类型的实例。我发现自己必须解析对象列表。例如,可能存在IntParser extends Parsable<Integer>,我想实现IntListParser extends Parsable<List<Integer>>。这可以非常简单地完成:

public class IntListParser extends Parsable<List<Integer>> {
  List<Integer> parse(String s) {
    IntParser ip = new IntParser();
    String[] strings = s.split(",");
    List<Integer> result;
    for (String s : strings) {
      result.add(ip.parse(s));
    }
    return result;
  }
}

这可以针对每种类型的解析器成功完成。在这个例子中,Integer没有什么特别之处。在写了几个相同的类后,我决定是时候创建一个通用的了:

public class GenericListParser<TParser extends Parsable<T>> extends Parsable<List<T>> {
  List<T> parse(String s) {
    TParser tp = new TParser();
    String[] strings = s.split(",");
    List<T> result;
    for (String s : strings) {
      result.add(tp.parse(s));
    }
    return result;
  }
}

不幸的是,这不起作用,因为命令new TParser()没有编译。有没有办法解决这个问题,或者我是否被迫为每种类型的Parser创建此代码的新副本?

我尝试过的解决方案是:

  • 解析静态。这样可以防止必须创建Parsables的实例,但它不起作用,因为您无法创建抽象的静态函数。
  • GenericListParser<TParser extends Parsable<T>>延长Parsable<T>而不是Parsable<List<T>>。这将允许其parse函数调用Parsable<T>的解析函数,因为它是它自己的超级函数。这不起作用,因为解析的返回类型为T,您无法将List<T>转换为T

2 个答案:

答案 0 :(得分:4)

不是试图为未知的东西创建解析器,而是将其作为参数接受:

public class GenericListParser<TParser extends Parsable<T>> extends Parsable<List<T>> {
  private TParser tp = null;
  public GenericListParser(TParser parser) {
      this.tp = parser;
  }
  List<T> parse(String s) {
    String[] strings = s.split(",");
    List<T> result;
    for (String s : strings) {
      result.add(tp.parse(s));
    }
    return result;
  }
}

答案 1 :(得分:2)

我认为您的方法不是正确的方法,您应该删除所有列表解析类并替换它们,以及新的&#34;泛型&#34; class,使用单一类型的静态实用程序方法:

public ststic <T> List<T> parseList(String s, Parsable<T> p) {
    List<T> result = new ArrayList<>();
    for (String s : s.split(","))
        result.add(p.parse(s));
    return result;
}

现在你可以这样称呼它:

List<Integer> ints = parseList("1,2,3", new IntParser());

如果每个列表解析器需要单独的类,则:

public abstract class ListParser<T> extends Parsable<List<T>> {
    private final Parsable<T> Parsable;
    protected ListParser(Parsable<T> p) {
        parsable = p;
    }
    public List<T> parse(String s) {
        List<T> result = new ArrayList<>();
        for (String s : s.split(","))
            result.add(parsable.parse(s));
        return result;
    }
}

然后使用:

public class IntListParser extends ListParser<Integer> {
    public IntListParser() {
        super(new IntParser());
    }
}