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
这样的解释太肤浅了,完全是基于文字的描述,有没有基于代码层面的解释,或者其他的更深层次的解释呢?
ご理解のとおり
例 1 は確かに true
对象的数据的修改
ですが、例 2 は true参数本身的修改
値渡しであっても参照渡しであっても、本質的には
值传递
と同じです。メソッドが呼び出されるとき、パラメーターの値が計算され、対応するパラメーターにコピーが与えられます。オブジェクト型の場合のみ、オブジェクトの参照 (またはポインター、アドレスとして理解される) 値が渡されますが、パラメーターはコピーされた参照を取得しますが、元の参照と同じオブジェクトを指すため、この参照によれば、オリジナルオブジェクトのデータを操作できます
2 番目の例では、メソッドを呼び出すときに、パラメーター
string
(メモリ内の文字列オブジェクトhello
のアドレスとして理解できます) の値を計算し、それをパラメーターstr
にコピーします。パラメータstr
は元のhello
文字列オブジェクトへの参照を取得しましたが (つまり、str
の値はstring
の値、つまりhello
のアドレスに等しい)、すぐにこの時点で、str
パラメータの後にhello
文字列が続きます。str
はhello
を指しなくなり、代わりにworld
を指します。このプロセスでは、メソッドの外では、hello
自体とメモリ内のhello
のアドレスはまったく変更されません。string
変数は、変更されることなく常にhello
文字列オブジェクトを指します。3 つの文にまとめると:
は
对象
传引用
2.は
原始类型
传值
3.などの不変型は自己を提供しません。変更関数では、各操作で新しいオブジェクトが生成されるため、特別に処理する必要があります。これは値渡しと考えることができます。
String,Integer, Double
整数は文字列と同じです。値を保持するクラス変数は Final プロパティであり、再割り当てまたは新しいオブジェクトの生成のみが可能です。 Integer がメソッド パラメータとしてメソッドに渡されると、それへの代入により、元の Integer の参照がメソッド内のスタック アドレスを指すことになり、元のクラス変数アドレスへのポインタが失われます。割り当てられた Integer オブジェクトに対して実行される操作は、元のオブジェクトには影響しません。リンクの説明
です。test1.a = "567"
、ここで変更するのは、test1
によって参照されるオブジェクトの属性str = "word"
ここで変更するのは、参照変数str
が指すオブジェクトです。簡単に言うと、シャオミンとシャオホンの2人ですが、シャオミンの手をロボットハンドに置き換えると、本当にシャオミンの手が変わりますが、シャオホンの名前をシャオミンに変えると…。シャオホン自身はまだ変わっていません。
Deeper、シャオミンとシャオホンはイベントに参加する予定なので、本名を知る必要がないため、コードネームAとBが割り当てられます。この時、Aさんは活動中に負傷し、ハンドルが機械式のものに取り替えられたが、その結果、活動後、シャオ・ミンの手は確かに機械式のものに取り替えられていた。しかし、BはCと名札を交換しただけで、カミングアウト後もシャオホンは依然としてシャオホンであり、Cに該当する人物にはなっていない。
ここで、アクティビティはメソッドであり、割り当てられたコードは仮パラメータです。仮パラメータへの直接代入は実際のパラメータには影響しませんが、仮パラメータによって参照されるオブジェクトのプロパティに値を割り当てると、実際には影響を受けます。オブジェクトのプロパティに影響を与えました。
理解に役立つかどうかを確認するために、コメント付きのコードを追加します。メソッド呼び出しの実際の処理にはスタックなどの知識も関係することを理解しておけば、それほど複雑ではありません。このコードには出力がありません。理解した後で出力を追加して、理解が正しいかどうかを確認できます。
リーリー値渡し、参照渡し
文字列を除いて、Java の他のすべてのオブジェクトは参照によって渡されます。
リーリー
私のコラムの冒頭で関連する知識のポイントについて触れましたが、あなたが少し混乱しているようですので、それをお勧めしたいと思います。
文字列は不変型であり、その値は不変であることを意味します。たとえば、
String a = "abc"
では、メモリ内の参照 a はメモリ ブロック "abc" を指します。a = "bcd"
を使用すると、"abc" が配置されているメモリ ブロックの値は "bcd" に変更されません。別の文字列「bcd」が生成され、a が「bcd」を指すため、メソッドの外部の参照は引き続き「abc」のメモリを指します。変数型は、「abc」が配置されているメモリの値を直接変更します。このように、メソッドの外部の参照は依然として元のメモリ アドレスを指しているため、変更された値はメソッドの外部からアクセスできます。
String オブジェクトに含まれる文字列は変更できません。String 型変数が再割り当てされると、その参照も変更され、新しいオブジェクトになります。