web-dev-qa-db-fra.com

Java - L'état de l'objet ne change pas après l'appel de la méthode

Question Java débutante, mais je ne comprends pas comment fonctionne call-by-Value (ou Reference) dans l'exemple ci-dessous - 

Comment se fait-il que la valeur String ne soit pas modifiée après la sortie de la méthode alors que mon objet String personnalisé l’est. ? Même avec d'autres classes comme Date ..

public class StringMadness {

public static void main(String[] args) {
    String s = "Native String";
    CustomStringObject cs = new CustomStringObject();
    System.out.println("Custom String Before: " + cs.str);
    hello(cs);
    System.out.println("Custom String After: " + cs.str);

    System.out.println("Native String Before: " + s);
    hello(s);
    System.out.println("Native String After: " + s);
}

private static void hello(String t) {
    t = "hello " + t;
}

private static void hello(CustomStringObject o) {
    o.str = "hello " + o.str;
  }
}

class CustomStringObject {

String str = "Custom String";
}
11
Anand Hemmige

Comparez ces deux méthodes:

private static void hello(String t) {
    t = "hello " + t;
}

private static void hello(CustomStringObject o) {
    o.str = "hello " + o.str;
}

Dans le premier cas, vous attribuez une nouvelle valeur à t. Cela n'aura aucun effet sur le code appelant - vous ne faites que changer la valeur d'un paramètre et tous les arguments sont passés par valeur en Java.

Dans le second cas, vous attribuez une nouvelle valeur à o.str. Cela change la valeur d'un champ dans l'objet auquel se réfère la valeur de o. L'appelant voudra verra ce changement, car l'appelant aura toujours une référence à cet objet.

En bref: Java utilise toujours la méthode passe par valeur, mais vous devez vous rappeler que pour les classes, la valeur d'une variable (ou de toute autre expression) est une référence, pas un objet. Vous n'avez pas besoin d'utiliser le paramètre passant pour voir ceci:

Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"

La deuxième ligne ici copie la valeur de foo1 dans foo2 - les deux variables font référence au même objet. La variable que vous utilisez pour y accéder importe peu.

23
Jon Skeet

Il existe une différence importante entre les deux méthodes: en utilisant hello(String), vous essayez de remplacer la reference par la/la String et avec hello(CustomObject), avec une référence, vous utilisez la référence pour modifier un membre de l'objet. .

hello(String) prend une référence à une String. Dans la fonction que vous essayez de changer sur l'objet pointé par la référence, vous ne modifiez que la copie copie par valeur de la référence. Ainsi, vos modifications ne sont pas reflétées en dehors de la méthode.

hello(CustomObject) reçoit une copie d'une référence à un objet, que vous pouvez ensuite utiliser pour modifier l'objet réel. Considérez ceci comme une modification du contenu de l'objet. Ainsi, vos modifications sont sont reflétées dans l'appelant.

Etant donné un référence à un objet, vous pouvez changer cet objet en utilisant ses méthodes/champs exposés

4
pb2q

t désignera un nouvel objet et ne s'appliquera qu'à la méthode, donc les modifications ne seront pas visibles à l'extérieur.

Dans le second cas, la valeur que vous modifiez sera mise à jour en objet. Ces modifications sont donc visibles après l'appel de la méthode.

0
kosa

Ne fonctionne pas car String est un objet immuable

0
Roberto

Parce que pour la chaîne, vous modifiez simplement la référence du paramètre local.

0
kgautron