在这个例子中使用泛型的正确方法是什么?

时间:2016-01-19 21:20:42

标签: java generics

FileReader fileReader = null;
Object reader = null;
String dataRow = null;

fileReader = new FileReader(new File(fileLocation));
if (extension.equals("csv")) 
{
    reader = new CSVReader(fileReader);
} 
else 
{
    reader = new BufferedReader(fileReader);
}  

while (null != (dataRow = reader.readLine())) 
{
    ...
}

我们的想法是根据文件类型使用不同的类型,以便删除重复的代码。但是,我在最后一行收到错误,因为reader是Object类型。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

也许你可以制作两种方法:

public String read(CSVReader c){
    return c.readLine();
}

public String read(BufferedReader br){
    return br.readLine();
}

然后,在您当前的代码中:

if(extension.equals("csv"))
    dataRow = read(new CSVReader(fileReader));
else
    dataRow = read(new BufferedReader(fileReader));

这种重载将消除对包装类的需求。

如果你真的想使用包装类,我建议在某个地方使用它:

public interface MyIO{
    public String readLine();
}

public class MyBr extends BufferedReader implements MyIO{}

public class MyCSV extends CSVReader implements MyIO{}

然后,在您的代码中:

MyIO reader;
if(extension.equals("csv"))
    reader = new MyCSV(fileReader);
else
    reader = new MyBr(fileReader);

您会注意到两者的代码行数相同,并且(在我看来)这些方法更容易理解。

答案 1 :(得分:1)

回答指出,即使你的类型不合作,也可以使用泛型。您只需要分别为每种类型定义特化。我在这里只是在Java 8中添加一个草图。不确定你的意思'正确的方式',对所有事情都有利有弊......特别是在Java中。

将通用代码放在一个共同的超类中更简单:

interface GenericExample {
    interface InputGenericCode<Input> {

        /**
         * This is implemented in subtypes. 
         * 
         * @param x
         * @return
         */
        String readLine(Input x);

        default void genericAlgorithm(Input x) {
            // algorithm expressed generically here...
            for (;;) {
                String lineString = readLine(x);
                System.out.println("" + lineString);
            }
        }
    }

    public class BufferedReaderInputGenericCode implements InputGenericCode<BufferedReader> {

        @Override
        public String readLine(BufferedReader x) {
            try {
                return x.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public class CSVReaderInputGenericCode implements InputGenericCode<CSVReader> {

        @Override
        public String readLine(CSVReader x) {
            return x.readLine();
        }
    }

    static class CSVReader {

        public CSVReader(FileReader fileReader) {
            throw new RuntimeException("implement this");
        }

        public String readLine() {
            throw new RuntimeException("implement this");
        }
    }

    public static void main(String fileLocation, String extension) {
        FileReader fileReader = openFile(fileLocation);

        if (extension.equals("csv")) {
            CSVReader reader = new CSVReader(fileReader);
            new CSVReaderInputGenericCode().genericAlgorithm(reader);
        } else {
            BufferedReader reader = new BufferedReader(fileReader);
            new BufferedReaderInputGenericCode().genericAlgorithm(reader);
        }

        // dataRow = reader.readLine();
    }

    public static FileReader openFile(String fileLocation) {
        FileReader fileReader = null;

        try {
            fileReader = new FileReader(new File(fileLocation));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        return fileReader;
    }
}

更复杂的方式:

interface GenericExample {
    /**
     * All generic operations. 
     * 
     * @author jonasn
     *
     * @param <Input>
     */
    interface InputGenerics<Input> {
        String readLine(Input x);
    }
    interface InputGenericCode {
        public static <Input> void genericAlgorithm(Input x, InputGenerics<Input> generics) {
            // algorithm expressed generically here...
            for (;;) {
                String lineString = generics.readLine(x);
                System.out.println("" + lineString);
            }
        }
    }

    static class CSVReader {

        public CSVReader(FileReader fileReader) {
            // TODO Auto-generated constructor stub
        }
        public String readLine() {
            throw new RuntimeException("not implemented");
        }
    }
    public class CSVReaderInputGenerics implements InputGenerics<CSVReader> {
        @Override 
        public String readLine(CSVReader x) {
            return x.readLine();
        }
    }
    public class BufferedReaderInputGenerics implements InputGenerics<BufferedReader> {
        @Override 
        public String readLine(BufferedReader x) {
            try {
                return x.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                throw new RuntimeException(e);
            }
        }
    }
    public static void main(String fileLocation, String extension) {
        // String fileLocation = "whatever";
        // String extension = "";

        FileReader fileReader = null;
        // Object reader = null;
        String dataRow = null;

        try {
            fileReader = new FileReader(new File(fileLocation));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        if (extension.equals("csv")) 
        {
            CSVReader reader = new CSVReader(fileReader);
            InputGenericCode.genericAlgorithm(reader, new CSVReaderInputGenerics());
        } 
        else 
        {
            BufferedReader reader = new BufferedReader(fileReader);
            InputGenericCode.genericAlgorithm(reader, new BufferedReaderInputGenerics());
        }  

        // dataRow = reader.readLine();
    }
}