Java 使用字符串类名实例化泛型变量

Java 使用字符串类名实例化泛型变量,java,csv,generics,Java,Csv,Generics,我正在使用google的CSVReader,它需要一个类名来创建解析器。使用解析器,我将CSV文件读入列表 考虑以下代码: ValueProcessorProvider provider = new ValueProcessorProvider(); CSVEntryParser<A> entryParser = new AnnotationEntryParser<A>(A.class, provider); CSVReader<A> new

我正在使用google的CSVReader,它需要一个类名来创建解析器。使用解析器,我将CSV文件读入列表

考虑以下代码:

ValueProcessorProvider provider = new ValueProcessorProvider();
    CSVEntryParser<A> entryParser = new AnnotationEntryParser<A>(A.class, provider);

    CSVReader<A> newExternalFileCSVReader = 
            new CSVReaderBuilder<A>(m_NewExternalFile).entryParser((CSVEntryParser<A>) entryParser).strategy(new CSVStrategy(',', '"', '#', true, true)).build();
    List<A> m_NewExternalFileData = newExternalFileCSVReader.readAll();
ValueProcessorProvider提供程序=新的ValueProcessorProvider();
CSVEntryParser entryParser=newannotationentryparser(A.class,provider);
CSVReader新外部文件CSVReader=
新建CSVReaderBuilder(m_NewExternalFile).entryParser((CSVEntryParser)entryParser).strategy(新建CSVStrategy(‘,‘,‘,‘,‘,‘,‘,‘,‘,‘,‘,’,true)).build();
List m_NewExternalFileData=newExternalFileCSVReader.readAll();
使用此代码,我可以读取特定于a类的CSV文件。
我还有其他几个类:B、C、D,它们都使用上面相同的代码,只是使用它们各自的类


是否有一个函数,我将类名作为字符串传递,它可以基于字符串输入名实例化CSVReader/解析器?在这个函数中,我不必创建3个不同的代码段(对于类B、C、D),而可以使用相同的代码段,只需输入相关的类名?

您可以使用工厂模式

创建一个接口并在A、B、C和D的基本方法内部定义

然后所有A、B、C和D类都必须实现该接口

public interface BaseInterface {
    // your methods
}
然后创建一个工厂类,在其中传递一个标识符,它将返回正确启动的读取器

package a;

public final class Factory {

    // Not instantiable
    private Factory() {
        throw new AssertionError("Not instantiable");
    }

    public static CSVReader<your interface> getReader(String reader) {

        if ("A".equals(reader)) {
            return new CSVReader<A>();
        } else if ("B".equals(reader)) {
            return new CSVReader<B>();
        }
        // TODO create all your readers
    }
}
a包;
公共末级工厂{
//不可实例化
私人工厂(){
抛出新断言错误(“不可实例化”);
}
公共静态CSVReader getReader(字符串读取器){
如果(“A”。等于(读卡器)){
返回新的CSVReader();
}否则,如果(“B”。等于(读卡器)){
返回新的CSVReader();
}
//要创建所有的读者吗
}
}
现在,您可以通过factory类调用阅读器,如下所示:

ValueProcessorProvider provider = new ValueProcessorProvider();
    CSVEntryParser<A> entryParser = new AnnotationEntryParser<A>(A.class, provider);

    CSVReader<your interface> newExternalFileCSVReader = 
            Factory("your reader type");
    List<your interface> m_NewExternalFileData = newExternalFileCSVReader.readAll();
ValueProcessorProvider提供程序=新的ValueProcessorProvider();
CSVEntryParser entryParser=newannotationentryparser(A.class,provider);
CSVReader新外部文件CSVReader=
工厂(“您的阅读器类型”);
List m_NewExternalFileData=newExternalFileCSVReader.readAll();
由于您没有发布A、B、C和D类,因此您必须自定义该代码,但按照这种方式,我认为您可以实现您想要的功能。

您可以这样做:

public class MyCSVReader<T> {

    private Class<T> clazz;

    public MyCSVReader(Class<T> clazz) {
        this.clazz = clazz;
    }

    public List<T> readData(File file) {
        ValueProcessorProvider provider = new ValueProcessorProvider();
        CSVEntryParser<T> parser = new AnnotationEntryParser<T>(clazz, provider);
        CSVStrategy strategy = new CSVStrategy(',', '"', '#', true, true);
        CSVReaderBuilder builder = new CSVReaderBuilder<T>(file);
        CSVReader<T> reader = builder.entryParser(parser ).strategy(strategy).build();
        return reader.readAll();
    }
}
公共类MyCSVReader{
私人课堂;
公共MyCSVReader(clazz类){
this.clazz=clazz;
}
公共列表读取数据(文件){
ValueProcessorProvider提供程序=新的ValueProcessorProvider();
CSVEntryParser parser=newannotationentryparser(clazz,provider);
CSVStrategy strategy=新CSVStrategy(“,”,“,”,“#”,true,true);
CSVReaderBuilder=新CSVReaderBuilder(文件);
CSVReader reader=builder.entryParser(parser).strategy(strategy.build();
返回reader.readAll();
}
}
然后你会做:

MyCSVReader<A> readerA = new MyCSVReader<>(A.class);
List<A> data = readerA.readData(m_NewExternalFile);
MyCSVReader readerA=新的MyCSVReader(A.class);
List data=readerA.readData(m_NewExternalFile);
其他课程也一样

编辑:按文件扩展名查找类型可能有用吗

public class MyCSVReaderFactory {

    private static Map<String, MyCSVReader<?>> readersByFileExtension = new HashMap<>();

    // files with data for class A have extension .xta, etc.
    static {
        readersByFileExtension.put(".xta", new MyCSVReader<>(A.class));
        readersByFileExtension.put(".xtb", new MyCSVReader<>(B.class));
    }

    public MyCSVReader<?> create(String fileExtension) {
        MyCSVReader<?> reader = readersByFileExtension.get(fileExtension);
        if (reader == null) {
            throw new IllegalArgumentException("Unknown extension: " + fileExtension);
        }
        return reader;
     }
}

public List<?> doStuff(File file) {
    String fileExtension = getFileExtension(file);
    MyCSVReader<?> reader = MyCSVReaderFactory.create(fileExtension);
    return reader.readAll();
}

private String getFileExtension(File file) { 
    // TODO: implement this
}
公共类MyCSVReaderFactory{
私有静态映射创建(字符串文件扩展名){
MyCSVReader reader=readersByFileExtension.get(fileExtension);
如果(读卡器==null){
抛出新的IllegalArgumentException(“未知扩展名:“+fileExtension”);
}
返回读取器;
}
}
公共列表文件(文件){
字符串fileExtension=getFileExtension(文件);
MyCSVReader reader=MyCSVReaderFactory.create(文件扩展名);
返回reader.readAll();
}
私有字符串getFileExtension(文件名){
//TODO:实现这一点
}

如果您不想要一个列表(对象),那么类a-D应该实现一个公共接口或扩展一个可用于泛化的公共超类。

a、B、C和D是否以任何方式相关或类似?我认为您没有纠正以下代码,CSVReaderBuilder builder=new CSVReaderBuilder(file)//它仍然是指类AIf如果这回答了你的问题,请接受答案。