簡體   English   中英

使用字符串類名實例化泛型變量

[英]Instantiate a generic variable using string class name

我正在使用谷歌的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();

使用此代碼,我可以讀取特定於A類的CSV文件。
我還有其他幾個類:B,C,D,它們都使用上面相同的代碼,只是它們各自的類。

可以有一個函數,我將類名稱作為String傳遞,它可以根據String輸入名稱實例化CSVReader /解析器嗎? 而不是必須創建3個不同的代碼段(對於類B,C,D),我可以使用相同的一個,只需輸入相關的類名?

您可以使用工廠模式。

創建一個接口並在A,B,C和D的基本方法內定義。

然后所有A,B,C和D類都必須實現該接口。

public interface BaseInterface {
    // your methods
}

然后創建一個Factory類,在該類中傳遞一個標識符,它將使您的閱讀器正確啟動

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

現在,您可以通過您的工廠類呼叫讀者,如下所示:

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();

由於你沒有發布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<A> readerA = new MyCSVReader<>(A.class);
List<A> 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
}

如果您不需要List(對象),則AD類應實現公共接口或擴展可用於概括的公共超類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM