2010-05-12 9 views
3

Это мой первый класс Hello.javaПочему это приложение Java напечатано «true»?

public class Hello { 
    String name = ""; 
} 

Это мой второй класс Test1.java

public class Test1 {  
    public static void main(String[] args) { 
     Hello h = new Hello(); 
     Test1 t = new Test1(); 
     t.build(h); 
     System.out.println(h.name); 
    } 
    void build(Hello h){ 
     h.name = "me"; 
    } 
} 

Когда я бегу Test1.java, он печатает "меня". Я думаю, я понимаю, из-за «ссылки передачи».

Это мой третий класс Test2.java

public class Test2 { 
    public static void main(String[] args) { 
     Hello h = null; 
     Test2 t = new Test2(); 
     t.build(h); 
     System.out.println(h == null); 
    } 
    void build(Hello h){ 
     h = new Hello(); 
    } 
} 

Когда я бегу Test2.java, он печатает "истина", то почему? Это «передача ссылок» больше не существует? Я запутался.

+2

Возможный дубликат [Is Java pass by reference?] (Http://stackoverflow.com/questions/40480/is-java-pass-by-reference) – polygenelubricants

+0

Java проходит по значению. Java передает ссылки по значению. – polygenelubricants

+1

эти круглые скобки? программист? : -P –

ответ

7

Как вы, наверное, знаете, Java - это вызов по значению. Wenn вы передаете ссылку, эта ссылка копируется. Конечно: сама ссылка и не копия цели ссылки копируется.

Давайте посмотрим на ваш первый образец: при вызове build() будет скопирована ссылка h. Потому что h (копия в build()) не переписывается где-то в build(), он всегда указывает на расположение памяти оригинала h. Поэтому изменение h.name влияет на оригинал h.

Образец 2 отличается: ссылка h также копируется. Но h перезаписывается в build(). Эффект заключается в том, что оригинальные h и h в build() указывают на разные места памяти! h в build() указывает на только что сгенерированный объект Hello, который будет собирать мусор после возвращения метода build().

+0

Это очень ясно, спасибо. –

-1

Поскольку h равно нулю.

+3

Он спрашивает * почему * h равно нулю, то есть зачем делать 'h = new Hello()' внутри сборки не влияет на h в main. – sepp2k

3

Java всегда пройти по значению. Когда у вас есть ссылки, он просто передает копию ссылки, указывающей на тот же объект. В вашем случае вы просто перенаправляете скопированную ссылку на другой объект. Вот почему ваш оригинал не изменился.

0

h.name = "me" изменяет объект, на который ссылается h. Это изменение будет видно из любого другого места, где упоминается тот же объект. h = new Hello() делает h ссылкой на другой (новый) объект. Это изменение влияет только на эту конкретную переменную h - не любую другую переменную, которая ранее ссылалась на один и тот же объект.

1

У вас есть две различные переменные h. Первый локальный - main. Второй локальный - build.

Если переименовать build переменную x, это должно стать очевидным, почему h в main не влияет.

Edit:

public class Test2 { 
    public static void main(String[] args) { 
     Hello h = null; 
     Test2 t = new Test2(); 
     t.build(h); 
     System.out.println(((h == null))); 
    } 
    void build(Hello x){ 
     x = new Hello(); 
    } 
} 

Здесь вы можете ясно видеть, x начинается как null. Тогда x станет новым объектом. Затем умирает x. h ничего не знает о том, что происходит в жизни x.

0

В Test1.java, когда вы проходите Hello объект h построить() метод, переменная main().h и build().h указывают на тот же объект в памяти.

main().h = build().h => pointing same object т.е.

Но в Test2.java, даже если вы передаете main().h построить() метод, позже внутри метода сборки, вы переуказание build().h к новому объекту. Но это не влияет на main().h

i.e. main().h != build().h // оба они указывают разные объекты.

вот почему main().h по-прежнему содержит null, и ваша программа верна.

0

Прежде всего вам нужно понять разницу между объектом и ссылкой.

В первом случае вы непосредственно обращаетесь к объекту (память в куче) и изменяете значение, где, как и во втором случае, ссылка будет иметь новый объект до конца метода. После этого он больше не будет доступен.

public static void main(String[] args){ 
      String str = null; 
      System.out.println(getString(str)== null); 
    } 

    public static String getString(String s){ 
      s = new String(); 
      return s; 
    } 

Приведенный выше код будет печатать ложные

0

Выражаясь просто:

1) Сначала необходимо создать переменную 'H' и указать его обнулить

2) Когда вы входите в метод «void build (Hello h)», вы создаете новую переменную (также называемую «h»), которая получает указатель на нуль (указатель на то, на что указывает указатель, является COPIED).

3) Когда вы делаете «h = new Hello()», вы затем изменяете новую переменную «h» в методе, указывая на новый экземпляр Hello (new Hello()).

Исходная переменная, называемая «h», не изменяется.

Простой, как пирог.

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