我试图创建一个可以从文件中读取序列化对象的通用loadFile方法。但是,对象类型可能会根据要加载的文件而有所不同。我显然误解了铸造是如何工作的,但却无法真正找到我应该在这里做的事情。
以下是我的FileAdapter类:
public class FileAdapter {
public ArrayList<Transaction> loadTransactions() {
return (ArrayList<Transaction>) loadFile(new File("data/transactions.ser"));
}
public ArrayList<Fund> loadFunds() {
return (ArrayList<Fund>) loadFile(new File("data/funds.ser"));
}
private ArrayList<Object> loadFile(File file) {
ArrayList<Object> obj = new ArrayList<>();
FileInputStream fis = new FileInputStream(file);
in = new ObjectInputStream(fis);
obj = (ArrayList<Object>) in.readObject();
return obj;
}
}
可以看出,我有两种方法从文件加载不同类型的对象,但我想共享实际加载文件的代码。是我试图做到可行但是错误地实施了,或者如果类型不同,这根本不起作用吗?
答案 0 :(得分:4)
可以通过在方法loadFile
的定义中定义bounded type parameter来完成,如下所示:
public ArrayList<Transaction> loadTransactions(){
return loadFile(new File("data/transactions.ser"));
}
public ArrayList<Fund> loadFunds(){
return loadFile(new File("data/funds.ser"));
}
private <T> ArrayList<T> loadFile(File file) {
ArrayList<T> obj = new ArrayList<>();
...
return (ArrayList<T>) in.readObject();
}
答案 1 :(得分:1)
如果你想确定你的代码不会盲目地进行,除非List实际上包含你期望它包含的内容,将元素类型传递给你的方法,并使用Class.cast
来确保每个元素都是你的期待它:
public ArrayList<Transaction> loadTransactions() {
return loadFile(new File("data/transactions.ser"), Transaction.class);
}
public ArrayList<Fund> loadFunds() {
return loadFile(new File("data/funds.ser"), Fund.class);
}
private <T> ArrayList<T> loadFile(File file,
Class<T> elementType) {
ArrayList<?> obj;
try (FileInputStream fis = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fis)) {
// This is safe, because it does not make any assumptions
// about the ArrayList's generic type.
obj = (ArrayList<?>) in.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
ArrayList<T> typedList = new ArrayList<>(obj.size());
for (Object element : obj) {
typedList.add(elementType.cast(element));
}
return typedList;
}
如果忽略编译器的“不安全”警告,则可能会在远离实际编码错误的位置发生奇怪的错误,这使得它们很难调试。
执行(ArrayList<Object>) in.readObject()
时,如果对象不是ArrayList,您将立即获得ClassCastException,这是一件好事。该异常会阻止您的代码在读取其他内容时使用ArrayList的错误假设继续进行。
但泛型类型,无论是<Object>
还是<Fund>
还是其他任何类型,都是由于类型擦除而在运行时不存在的信息。因此,无论ArrayList包含什么,不安全的通用转换都不会抛出任何异常。只有在稍后,当您尝试从ArrayList读取元素时,才会发生ClassCastException。