Java передать по значению - вы можете это объяснить? - PullRequest
2 голосов
/ 06 июля 2010

Я прочитал эту превосходную статью , и это имеет смысл: Java строго передается по значению;когда объект является параметром, ссылка на объект передается значением .

Однако я совершенно не понимаю, почему следующий фрагмент может сработать.Foo имеет строковую переменную-член a, которая является неизменной и должна быть записана каждый раз.Первый способ записи (закомментированный) должен работать нормально, и он работает.Ссылка a второго набора методов на значение, которое было передано.Это не должно работать, если newstr является временной переменной.Ожидаемые выходные результаты:

Totally temp
NULL

Однако я получаю

Totally temp
Totally temp

Почему?Это просто удача, что временная ссылка на переменную все еще хороша?

public class Foo {
    String a;
    public Foo(){}
    public void burna(String newstr){
           // a = new String(newstr);
           a = newstr; /*this should not work: */ 
        }
}

public class foobar {
    Foo m_foo;
    public foobar(){};
    public void dofoo(){
        String temp = new String("Totally temp\n");
        m_foo.burna(temp);
        System.out.print(m_foo.a);
    }

}

 public static void main(String[] args) {
        Foo myfoo = new Foo();
        foobar myfoobar = new foobar();

        myfoobar.m_foo = myfoo;
        myfoobar.dofoo();
        System.out.print(myfoo.a);

    }

Ответы [ 6 ]

11 голосов
/ 06 июля 2010

Foo имеет строковую переменную-член a, которая является неизменной и должна быть записана каждый раз.

Нет, это не так: он не помечен как final:

public class Foo {
    String a;
    ...
}

Переменная является полностью изменяемой - вы можете изменить ее, чтобы в любое время ссылаться на другую строку, что вы и делаете в методе burna.

В настоящее время я не понимаю, почему вы думаете, что это не сработает:

public void burna(String newstr){
    a = newstr; /*this should not work: */ 
}

Это устанавливает значение из a равным значение из newstr - которое является ссылкой на строку (или ноль). Это все, что он делает. Я не уверен, что вы имеете в виду под «прожиганием» переменной.

Вы звоните burna и передаете ссылку на строку с текстом «Totally temp \ n», поэтому a устанавливается на ссылку на эту строку.

Что вы подразумеваете под «Не должно работать, если newstr - временная переменная». Нет такой вещи как «временная переменная». Существует переменная local - но объект не уничтожается только потому, что ссылающаяся на него переменная выходит из области видимости. Вас это смущает?

В вашей программе происходит несколько вещей - класс foobar, вероятно, не помогает вам с точки зрения понимания. Не могли бы вы попытаться упростить ваш код до такой степени, что он все еще сбивает вас с толку, но там меньше всего происходит? Тогда мы могли бы более точно выделить источник путаницы.

3 голосов
/ 06 июля 2010

Проблема в том, что вы не понимаете, как работает сборка мусора. Пока хотя бы одна ссылка на объект остается действительной, этот объект не будет собран.

2 голосов
/ 06 июля 2010

Объект String является неизменным, а объект Foo - нет.myfoobar.m_foo и myfoo указывают на один и тот же объект и, таким образом, разделяют элемент a.

2 голосов
/ 06 июля 2010

Есть две ссылки на строку "Totally temp \ n".Один - temp, другой - a в объекте Foo.В конце dofoo temp выходит за рамки, так что это на одну ссылку меньше.Однако у вас еще есть другая ссылка, поэтому строка не является сборщиком мусора.

1 голос
/ 06 июля 2010

Вы можете привыкнуть к тому, как переменные и объекты работают в C ++.

Переменные не примитивных типов всегда ссылаются на объекты в Java, в отличие от C ++, где переменные представляют сами объекты.

Объекты в Java всегда размещаются в куче. Объекты никогда не находятся в стеке * как «временные переменные», как в C ++.

*: на самом деле JVM может выполнять некоторые оптимизации и помещать объекты в стек, но это не имеет отношения к пониманию концепции работы переменных и объектов в Java.

0 голосов
/ 21 октября 2013

Поскольку Java также передает ссылки на объекты по значению. Теперь вот где это сложно:

public void tricky (точка arg1, точка arg2)

{

arg1.x = 100;

arg1.y = 100;

Точка temp = arg1;

arg1 = arg2;

arg2 = temp;

}

public static void main (аргументы String [])

{* * тысяча двадцать-один

точка pnt1 = новая точка (0,0);

Точка pnt2 = новая Точка (0,0);

System.out.println ("X:" + pnt1.x + "Y:" + pnt1.y);

System.out.println ("X:" + pnt2.x + "Y:" + pnt2.y);

System.out.println ("");

хитрым (pnt1, pnt2);

System.out.println ("X:" + pnt1.x + "Y:" + pnt1.y);

System.out.println ("X:" + pnt2.x + "Y:" + pnt2.y);
}

** Если мы выполним этот метод main (), мы увидим следующий вывод:

X: 0 Y: 0

X: 0 Y: 0

X: 100 Y: 100

X: 0 Y: 0 **

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...