2010-05-12 3 views
3

Ceci est ma première classe Hello.javaPourquoi cette application Java affiche-t-elle "true"?

public class Hello { 
    String name = ""; 
} 

Ceci est mon deuxième classe 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"; 
    } 
} 

Quand je lance Test1.java, il imprime "moi". Je pense que je comprends, à cause du "transfert de référence".

Ceci est ma troisième classe 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(); 
    } 
} 

Quand je lance Test2.java, il imprime "true", pourquoi? Est-ce que le "transfert de référence" n'est plus? Je suis confus.

+2

duplication possible de [Java passe par référence?] (Http://stackoverflow.com/questions/40480/is-java-pass-by-reference) – polygenelubricants

+0

Java passe en valeur. Java transmet les références par valeur. – polygenelubricants

+1

ces beaucoup de parenthèses? Programmeur Lisp Fromer? :-P –

Répondre

7

Comme vous le savez probablement, Java est appelé par valeur. Lorsque vous passez une référence, cette référence est copiée. Pour être sûr: La référence elle-même et pas la cible de la référence est copiée. Jetons un coup d'oeil à votre premier échantillon: En appelant build(), la référence h sera copiée. Parce que h (la copie dans build()) ne pas être écrasé quelque part dans build(), il pointe toujours à l'emplacement de mémoire de l'original h. Donc changer h.name affecte l'original h.

L'exemple 2 est différent: la référence h est également copiée. Mais h est écrasé dans build(). L'effet est que l'original h et le h dans build() pointent vers différents emplacements de mémoire! Le h en build() pointe vers l'objet Hello nouvellement généré, qui sera collecté par la poubelle quelquefois après le retour de la méthode build().

+0

C'est très clair, merci. –

-1

Parce que h est égal à null.

+3

Il demande * pourquoi * h est nul, c'est-à-dire pourquoi faire 'h = new Hello()' dans la construction n'affecte pas h dans main. – sepp2k

3

Java est toujours passer par la valeur. Lorsque vous avez des références, il transmet simplement une copie de la référence pointant vers le même objet. Dans votre cas, vous venez de rediriger la référence copiée vers un autre objet. C'est pourquoi votre original n'est pas changé.

0

h.name = "me" modifie l'objet référencé par h. Cette modification sera visible à partir de tout autre endroit où le même objet est référencé. h = new Hello() fait référence à un autre objet (nouveau). Cette modification n'affecte que cette variable particulière h - pas d'autre variable qui a déjà référencé le même objet.

1

Vous avez deux variables différentes h. Le premier est local à main. Le second est local au build.

Si vous renommez votre variable build à x, il devrait être évident pourquoi h dans main n'est pas affectée.

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(); 
    } 
} 

Ici vous pouvez voir clairement, x commence comme null. Alors x devient un nouvel objet. Puis x meurt. h ne sait rien de ce qui se passe dans la vie de x.

0

En Test1.java, lorsque vous passez la méthode Hello objet h à construire(), la main().h et build().h variables pointent vers un même objet en mémoire.

à savoir main().h = build().h => pointing same object

Mais Test2.java, même si vous passez méthode main().h pour construire(), puis sur la méthode de construction à l'intérieur, vous rejointoiement build().h à un nouvel objet. Mais cela n'affecte pas le main().h

c'est-à-dire main().h != build().h // ils pointent tous deux des objets différents.

C'est pourquoi main().h contient toujours null et votre programme s'imprime.

0

Tout d'abord, vous devez comprendre la différence entre l'objet et la référence. Dans le premier cas, vous accédez directement à un objet (mémoire en tas) et changez une valeur, alors que dans le second cas la référence aura le nouvel objet jusqu'à la fin de la méthode. Après cela, il ne sera plus accessible.

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; 
    } 

Le code ci-dessus imprimera faux

0

Pour faire simple:

1) Vous devez d'abord créer une variable 'h' et le point à null

2) Lorsque vous venez dans la méthode "void build (Hello h)" vous créez un nouveau variabel (aussi appelé 'h') qui est pointé sur null (le pointeur vers ce que la variable pointe vers est COPIED).

3) Lorsque vous faites 'h = new Hello()', vous changez la nouvelle variable 'h' dans la méthode pour pointer vers une nouvelle instance de Hello (new Hello()).

La variable d'origine appelée «h» est inchangée.

Simple comme une tarte.

Questions connexes