1、问题描述
java方法传String类型的参数时,为啥方法对值的修改没有在方法之外生效?假设是其他类型的对象,那么方法对对象的数据的修改是会在方法之外生效的啊,可是String类型也是对象类型啊,为啥就没有在方法之外生效呢?
2、代码示例
//示例1:对象类型
public class PassReferByValue
{
String a = "123";
public static void test(PassReferByValue test)
{
test.a = "abc";
}
public static void main(String[] args)
{
PassReferByValue test = new PassReferByValue();
System.out.println("对象的数据的初始值是:" + test.a); //123
test(test);
System.out.println("通过调用test方法修改对象的数据的值之后:" + test.a); //abc
}
}
总结:因为是对象类型,所以方法每次修改对象的数据的值之后,都在方法之外生效了,也就是说,在方法之外和在方法之内访问到的对象的数据的值是一致的。
//示例2:String类型
public class Test
{
public static void test(String str)
{
str = "word";
}
public static void main(String[] args)
{
String string = "hello";
System.out.println("对象的数据的初始值是:" + string); //hello
test(string);
System.out.println("通过调用test方法修改对象的值之后还是以前的值:" + string); //hello
}
}
总结:如果方法的参数是String类型,虽然方法修改了它的值,但是并没有在方法之外生效,也就是说,在方法之外和在方法之内的访问到的值不一样!!!这是为什么???
3、网上的解释
String等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。
http://blog.csdn.net/fbysss/article/details/3082949
这样的解释太肤浅了,完全是基于文字的描述,有没有基于代码层面的解释,或者其他的更深层次的解释呢?
Selon votre compréhension
L'exemple 1 est bien vrai
对象的数据的修改
, mais l'exemple 2 est vrai参数本身的修改
Qu'il s'agisse d'un passage par valeur ou d'un passage par référence, c'est essentiellement la même chose que
.值传递
Lorsque la méthode est appelée, la valeur du paramètre est calculée et une copie est donnée au paramètre correspondantUniquement pour les types d'objet, la valeur de référence (ou comprise comme pointeur, adresse) de l'objet est transmise. Bien que le paramètre obtienne une référence copiée, il pointe vers le même objet que la référence d'origine, donc selon cette référence, vous pouvez exploiter les données de l'objet d'origine
Dans votre deuxième exemple, lors de l'appel de la méthode, calculez la valeur du paramètre
string
(qui peut être compris comme l'adresse de l'objet chaînehello
en mémoire) et copiez-la dans le paramètrestr
, bien que le paramètrestr
ait obtenu la référence à l'objet chaînehello
d'origine (c'est-à-dire que la valeur destr
est égale à la valeur destring
, c'est-à-dire l'adresse dehello
), mais immédiatement a donné ce paramètre Réaffecter. À l'heure actuelle, le paramètrestr
n'a rien à voir avec la chaînehello
str
ne pointe plus vershello
mais pointe versworld
. ethello
Il n'y a aucun changement dans l'adresse en mémoire, et la variablehello
en dehors de la méthode pointe toujours vers l'objet chaînestring
sans aucun changementhello
Pour résumer en trois phrases :
1
对象
est传引用
2
原始类型
est传值
3. Fonction de modification, chaque opération génère un nouvel objet, il doit donc être traité spécialement. Cela peut être considéré comme un passage par valeur.
String,Integer, Double
Integer est identique à String. La variable de classe qui contient la valeur est une propriété Final et ne peut pas être modifiée. Elle peut uniquement être réaffectée/générer un nouvel objet. Lorsqu'un entier est transmis à la méthode en tant que paramètre de méthode, son affectation fera pointer la référence de l'entier d'origine vers l'adresse de la pile dans la méthode, perdant ainsi le pointeur vers l'adresse de la variable de classe d'origine. Toute opération effectuée sur l’objet Integer attribué n’affectera pas l’objet d’origine.Description du lien
test1.a = "567"
, ce que vous modifiez ici, c'est l'attributtest1
de l'objet référencé parstr = "word"
Ce que vous modifiez ici, c'est l'objet pointé par la variable de référencestr
.Pour faire simple, il y en a deux, Xiao Ming et Xiao Hong Si vous remplacez la main de Xiao Ming par une main de robot, la main de Xiao Ming sera vraiment changée, mais si vous changez le nom de Xiao Hong en Xiao Ming... Xiao Hong lui-même n'est toujours pas le même.
Plus profondément, Xiao Ming et Xiao Hong vont participer à un événement. L'événement ne nécessite pas que vous connaissiez votre vrai nom, ils se voient donc attribuer les noms de code A et B. À ce moment-là, A a été blessé pendant l'activité et la poignée a été remplacée par une main mécanique. En conséquence, après l'activité, la main de Xiao Ming a effectivement été remplacée par une main mécanique. Mais B vient d'échanger le badge contre C. Après sa sortie, Xiao Hong est toujours Xiao Hong et n'est pas devenu la personne correspondant à C.
Ici, l'activité est la méthode, et le code attribué est le paramètre formel. L'attribution directe de valeurs aux paramètres formels n'affectera pas les paramètres réels, mais l'attribution de valeurs aux propriétés de l'objet référencé par. les paramètres formels ont en fait affecté les propriétés de l'objet.
Je vais ajouter un morceau de code avec des commentaires pour voir si cela peut vous aider à comprendre. Si vous voulez comprendre que le véritable processus d’appel de méthode implique également des connaissances telles que la pile, ce n’est pas si compliqué. Ce code n'a aucune sortie. Vous pouvez essayer d'ajouter une sortie après l'avoir compris pour vérifier si votre compréhension est correcte.
Passez par valeur, passez par référence
À l'exception de String, les autres objets en Java sont passés par référence.
J'ai évoqué des points de connaissances pertinents au début d'une de mes chroniques. Voyant que vous êtes un peu confus, j'aimerais vous le recommander.
String est un type immuable, ce qui signifie que sa valeur est immuable. Par exemple,
String a = "abc"
, dans la mémoire, la référence a pointe vers le bloc mémoire "abc". Lors de l'utilisation dea = "bcd"
, la valeur du bloc mémoire où se trouve "abc" n'est pas changée en "bcd", mais une autre chaîne est générée. "bcd", puis pointez a vers "bcd", donc la référence en dehors de la méthode pointe toujours vers la mémoire de "abc".Le type de variable modifiera directement la valeur de la mémoire où se trouve "abc" De cette façon, la référence en dehors de la méthode pointe toujours vers l'adresse mémoire d'origine, donc la valeur modifiée est accessible en dehors de la méthode.
La chaîne contenue dans l'objet String ne peut pas être modifiée. Lorsqu'une variable de type String est réaffectée, sa référence changera également et deviendra un nouvel objet.