2013-07-27 3 views
-4

Я ожидаю, что NullPointerException на выходе следующей программы, потому что внутри метода go нумеруется c2. Но он отлично работает и печатает 200. Почему?Почему я не получаю исключение NullPointerException?

class CardBoard { 
    Short story = 200; 
    CardBoard go(CardBoard cb) { 
     cb = null; 
     return cb; 
    } 
    public static void main(String[] args) { 
     CardBoard c1 = new CardBoard(); 
     CardBoard c2 = new CardBoard(); 
     CardBoard c3 = c1.go(c2); 
     System.out.print(c2.story); // dout here 
    } 
} 

ответ

1

Вы направляете параметр функции go к нулю, а не переменная c2. Метод go может изменить содержимое параметра CardBoard при его исполнении (например, параметр story), но сам объект не будет «нулевым».

+0

он мог бы также думать о 'System.out.print (c3.story)', который бы кинуть NPE, а 'c3' было бы присвоено значение' null'. – akf

+0

только что отредактировал то, что ...? – user1612062

+0

@akf: возможно, и он получит там NPE. – drvdijk

0
  • A ссылка на c2 передается в путь.
  • ссылка присваивается параметру Сь
  • код метода присваивает нуль параметру переменной

Все это не имеет никакого влияния на содержание переменной c2 вне метода идут

1

Java использует pass by value semantics для вызовов методов. Это означает, что значение ссылки на c2 передается методу go, а не сама ссылка. Подумайте об этом так. Есть 4 слота памяти, 3, содержащие значения, указывающие на объекты, созданные в main, они называются c1, c2 и c3 соответственно, а другой - для хранения значения, переданного в go, с именем cb. Когда функция вызывается, значение в c2 копируется в слот cb. Затем метод go ставит значение null в слот cb. Это, однако, не меняет значение в слоте c2 - оно остается таким же, как и перед вызовом метода.

1

Is Java pass-by-value?.

Скажем, r2 является ссылкой на c2, скажем, 123 - значение этой ссылки. так r2 «проводит» 123, что является ничем иным, как c2's.

Теперь, когда вы звоните c1.go(c2), создается новая ссылка rN, которая содержит 123 и передается методу. И когда вы делаете c2 = null, это refrence rN, который становится null, а не c2.

0

Чтобы получить свой ожидаемый результат попробуйте использовать

`System.out.print(cb.story);` 

внутри метода go после nullingСь.

Или

System.out.print(c3.story); // dout here 

Теперь в вашем случае вы возвращаете null который присваивается c3. Поэтому вы не изменяете переменную c2.

Лучшие объяснениями я нашел об этих сомнениях является here

Всех ответов и комментарии стоит читать.

1

В параметрах Java передаются по значению, а не по ссылке, поэтому вы не изменяете переменную c2, вы просто «передаете» объект, к которому указывает c2.

Может быть, если вы использовали язык как C# вы можете сделать это в Java:

class CardBoard { 

    Short story = 200; 

    CardBoard go(byRef CardBoard cb) { // NOT REALLY ALLOWED, Compilation error 
     cb = null; 
     return cb; 
    } 

    public static void main(String[] args) { 
     CardBoard c1 = new CardBoard(); 
     CardBoard c2 = new CardBoard(); 
     CardBoard c3 = c1.go(byRef c2); // NOT REALLY ALLOWED, Compilation error 
     System.out.print(c2.story); // dout here 
    } 
} 

тогда вы будете модифицировать c2 себя, но единственное, что вы могли бы изменить бы внутреннее состояние объекта что вы проходите (ссылаясь на что-то вроде myObj.setSomething(x)).

0

Я думаю, вы неправильно поняли, как ссылки и объекты работ

Основная функция

CardBoard c1 = new CardBoard(); 

c1 |100| Address ---points to---> Memory address at location 100 

     CardBoard c2 = new CardBoard(); 
c2 |400| Address ---points to---> Memory address at location 400 

     CardBoard c3 = c1.go(c2); 
c3 |600| Address ---points to---> Memory address at location 600 

     System.out.print(c2.story); // dout here 

идти Функция

CardBoard go(CardBoard cb) { 

cb |400| Address ---points to---> Memory address at location 400 

New cb reference is created which also points to memory location where c2 is pointing(Note, cb and c2 are two different reference but pointing to same memory location) 

    cb = null; 
Above line changed cb reference to null, still c2 is pointing to same memory location. 
     return cb; 
    } 

Поэтому, когда функция идти вернулась нет никаких изменений с2.

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

центибар создается в другом стеке метод, то где c1, c2 и c3 создается

Смежные вопросы