Ошибка ссылки на переменную при загрузке объекта из файла в Java - PullRequest
0 голосов
/ 15 апреля 2010

У меня проблема со ссылкой на переменную при загрузке сохраненного сериализованного объекта из файла данных. Все переменные, ссылающиеся на один и тот же объект, похоже, не обновляются при изменении. Ниже приведен код, иллюстрирующий проблему.

    Tournament test1 = new Tournament();
    Tournament test2 = test1;

    try {
        FileInputStream fis = new FileInputStream("test.out");
        ObjectInputStream in = new ObjectInputStream(fis);

        test1 = (Tournament) in.readObject();

        in.close();

    }
    catch (IOException ex){
        Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
    }
    catch (ClassNotFoundException ex){
        Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
    }

    System.out.println("test1: " + test1);
    System.out.println("test2: " + test2);

После запуска этого кода test1 и test2 больше не ссылаются на один и тот же объект. Насколько мне известно, они должны это делать, поскольку в объявлении test2 содержится ссылка на test1. Когда test1 обновляется, test2 должен отражать изменения и возвращать новый объект при вызове в коде. Я что-то упустил здесь или я неправильно понял, как работают ссылки на переменные в Java?

Ответы [ 4 ]

3 голосов
/ 15 апреля 2010

Я что-то упустил здесь? или я ошибся в том, как ссылки на переменные в Java работают?

Скорее всего, вы неправильно поняли то, чему вас учили, или учили что-то не так. Все переменные ссылочного типа (то есть не примитивные типы) ссылаются directly на объект.

Tournament test1 = new Tournament();

Создает новый экземпляр Tournament и заставляет test1 обращаться к нему.

Tournament test2 = test1;

Копирует ссылку из test1 в test2, заставляя их ссылаться на один и тот же объект.

test1 = (Tournament) in.readObject();

Делает test1 ссылкой на другой объект, который был десериализован из потока, в то время как test2 все еще ссылается на исходный объект.

0 голосов
/ 15 апреля 2010

Вы нигде не "обновляете" test1.

В этой строке присваивается другой объект типа Tournament, который он читает из входного потока, и назначается этот новый объект test1:

test1 = (Tournament) in.readObject();

Между тем test2 все еще указывает на исходный объект, который был выделен в начале вашего блока кода.

0 голосов
/ 15 апреля 2010

Проблема в том, что Java передает и присваивает ссылки. Это не так. Java передает и присваивает по значению. Просто бывает, что со ссылочными типами переданное значение является ссылкой.

Разница заключается в следующем: Скажем, у вас есть тестовый код

Tournament test1 = new Tournament();
Tournament test2 = test1;

test1 = new Tournament();
System.out.println(test1 == test2 ? "Equal" : "Not Equal");

Если Java передается по ссылке, выдается Equal, поскольку test2 будет просто псевдонимом для test1 Однако, поскольку Java передается по значению, она печатает Not Equal.

0 голосов
/ 15 апреля 2010

Когда вы демонтируете объект с сериализацией и присваиваете его переменной, вы заменяете старую ссылку (в вашем случае new Tournament()) на новый объект .. поэтому test2 будет указывать на исходный Tournament, в то время как test1 будет ссылаться на только что не сериализованный объект.

Это как делать:

Tournament t1 = new Tournament();
Tournament t2 = t1;

t1 = new Tournament();

будет t1 == t2? Конечно нет ..

...