Это мой первый вопрос, так как до сих пор я всегда находил то, что мне нужно, но на этот раз что-то относительно простое сводит меня с ума. Итак, у меня есть этот класс:
public class QImage {
protected String imagePath;
public QImage() {
}
public QImage(String imgPath) {
imagePath = imgPath;
}
И тогда:
public class DImage extends QImage implements Serializable {
protected int imageId;
public DImage(String imagePath) {
imageId = 0;
}
И позже в коде:
private void saveData(String filePath, List<DImage> imap) {
try {
FileOutputStream fileImap = new FileOutputStream(filePath);
ObjectOutputStream objectImap = new ObjectOutputStream(fileImap);
for (DImage image : imap) {
objectImap.writeObject(image);
}
И сейчас вроде все в порядке, пока:
public List<DImage> loadData(String filePath) {
List<DImage> imap = new ArrayList<>();
try {
FileInputStream fileImap = new FileInputStream(new File(filePath+"_imap.dat"));
ObjectInputStream objectImap = new ObjectInputStream(fileImap);
while (true) {
try {
**imap.add((DImage) objectImap.readObject());**
} catch (EOFException e) {
break;
}
}
Я получаю String imagePath = null. Я уверен, что дело в конструкторах и преобразовании readObject в DImage, но я не знаю, как с этим справиться. Если я создам еще одну строку в DImage, которая не унаследована от QImage, все будет работать нормально.
Редактировать:
Я называю это просто:
Desc desc = new Desc();
List<DImage> imagesList = desc.loadData("C:\\collective.xml");
Дело в том, что конструктор по умолчанию вызывается, когда:
imap.add((DImage) objectImap.readObject());




Вы получаете imagePath==null, потому что конструктор QImage(String), который устанавливает это поле, никогда не выполняется классом DImage:
public class DImage extends QImage implements Serializable {
protected int imageId;
public DImage(String imagePath) {
super(imagePath); // <-- you have to call the constructor
imageId = 0;
}
Редактировать: Кроме того, вы должны сделать так, чтобы ваш класс QImage реализовал Serializable, потому что только поля классов, реализующих этот интерфейс, сохраняются / восстанавливаются (только что проверены).
На самом деле я сам пробовал, и он тоже не работает (поэтому я не упоминал об этом).
Если вы не понимаете, что происходит при выполнении, используйте пошаговую отладку при десериализации объекта (ов). В любом случае IMHO чтение и запись объектов через ObjectInpu / OutputStream устарело и очень небезопасно и больше не должно использоваться. Например, лучше использовать Джексона и сериализовать данные только в формате JSON (а не в коде и данных).
@Robert Source о небезопасности объектных потоков Java? И его код не показывает связи между элементом QImage#imagePath и параметром loadData(String filePath), поэтому, хотя он должен по-прежнему делегирует путь к своему супертипу, я не верю, что он показывает что-либо, что предполагает, что эти два связаны (хотя может показаться, что это было бы)
Да, imagePath и filePath вообще не связаны. При пошаговом запуске отладчика конструктор QImage по умолчанию (пустой) вызывается при преобразовании readObject в DImage, что меня не удивляет, но я понятия не имею, как его изменить. Его удаление приводит к исключению IOException.
Покажите, пожалуйста, где и как вы вызываете loadData, включая объявление и назначение аргументов, которые вы ему передаете.
Ага! Большое спасибо. О, я потратил много времени, пытаясь это исправить, и это было всего 2 слова :)
Покажите, где вы звоните
loadData