扩展集合泛型类的泛型类

时间:2014-03-26 05:50:55

标签: java generics

我在从文件中读取行时使用Guava's LineProcessor接口。我创建了一个名为Line Loader的类,它将存储读取的行。我希望它是通用的选择收集行应该存储,所以我写了这样的东西:

public abstract class LineLoader<T> implements LineProcessor<Collection<T>> {        
    private final Collection<T> result;

    public LineLoader() {
        this.result = init();
    }

    protected boolean add(final T line) {
        return result.add(line);
    }

    @Override
    public boolean processLine(final String line) throws Exception {
        final T data = parser.parseLine(line);

        if (data == null) {
            return false;
        }

        return add(data);            
    }

    @Override
    public Collection<T> getResult() {
        return result;
    }

    protected abstract Collection<T> init();
}

使用init()方法,我强制子类选择集合类型,例如:

public abstract class LinkedLineLoader<T> extends LineLoader<T> {
    @Override
    protected Collection<T> init() {
        return new LinkedList<T>();
    }
}

我计划这样做:

public class LineLoader<T> implements LineProcessor<C<T> extends Collection<T>> {        
    private final C<T> result;

    public LineLoader() {
        result = new C<T>();  
    }

    protected boolean add(final T line) {
        return result.add(line);
    }

    @Override
    public boolean processLine(final String line) throws Exception {
        final T data = parser.parseLine(line);

        if (data == null) {
            return false;
        }

        return add(data);            
    }

    @Override
    public C<T> getResult() {
        return result;
    }
}

以便后面的子句(如果需要)可以这样做:

public class LinkedLineLoader<T> extends LineLoader<LinkedList<T>> {

}

但这是不可能的。这个问题有一个干净的解决方案吗?

1 个答案:

答案 0 :(得分:1)

在Java中,不可能从泛型类型参数创建实例,因为泛型在运行时被擦除。此外,泛型类型参数本身不能声明其他类型参数,如C<T>。因此,您发布的代码完全是非法的,无法编译:

private final C<T> result; // illegal
result = new C<T>(); // illegal

除此之外,你对类型参数的声明本身也存在一些缺陷。以下代码不是合法的Java代码:

public class LineLoader<T> implements LineProcessor<C<T> extends Collection<T>>

它实际上应该看起来像像这样:

public class LineLoader<T, C extends Collection<T>> implements LineProcessor<C>

作为您问题的解决方案,您可以如上所示声明您的LineLoader,并添加一个受保护的构造函数,它将泛型集合作为参数:

public abstract class LineLoader<T, C extends Collection<T>> implements LineProcessor<C> {        
    private final C result;

    protected LineLoader(C collection) {
        result = collection;  
    }

    protected boolean add(final T line) {
        return result.add(line);
    }

    @Override
    public boolean processLine(final String line) throws IOException {
        final T data = parser.parseLine(line);

        if (data == null) {
            return false;
        }

        return add(data);            
    }

    @Override
    public C getResult() {
        return result;
    }
}

然后你就可以实现你的LinkedLineLoader

class LinkedLineLoader<T> extends LineLoader<T, LinkedList<T>> {
    public LinkedLineLoader() {
        super(new LinkedList<>());
    }
}