なぜのみJavaで値渡し?

手始めに、正しくこの質問に答えるために、それはより困難です。答えの二日目を終えたとき、私は、私もこの事を記述することができなかったことがわかった残念ながら、私はこの記事がオンライン平野FOUNDで物事を説明することができませんどのような、シンプルな言語を理解するのは簡単です。だから、私はこのことを念頭にあっ書きます。この記事では、私は、実際のパラメータと正式なパラメータ法で始まり、何から学んだJavaが唯一の値渡しなぜあなたに説明します。

時間のうわさ
この問題については、StackOverflowの上でも、広範な議論につながっていた、多くのプログラマは、この問題の同じ理解ではないように思われる、と人々のさえ多くは間違って理解しています。そこ値によって渡され、Javaで渡されたパラメータを知っている可能性があり、人々はあるが、なぜ言うことができませんでした。

深さの説明を開始する前に、あなたがアップ表示する前に、これらのエラーを修正する必要があります。あなたのアイデアを持っている場合は、この記事を読むために取る必要があります。

誤解:条件値が渡され、参照によって渡され、それは値が渡されること、の値である場合、区別は、コンテンツ配信です。参照は、参照によって渡された場合。

理解とエラー:Javaは、参照によって渡されます。

誤解3:渡された引数が値渡しされる一般的なタイプである場合、および参照によって渡されたオブジェクトの場合。

パラメータ実の参加
方法はJavaで定義されている全てのノウハウは、パラメータを定義することができます私たち。例えばJavaでは、メイン方法:

これは引数パラメータの内部です。パラメータは、プログラミング言語で正式なと実際のパラメータに分割されています。

パラメータの形式で:パラメータは、オブジェクトが場合関数パラメータ着信コールを受信するために使用された本体の関数名と関数の定義に使用されます。

実パラメータ:時間基準で関数を呼び出し、関数呼び出しと呼ばれる機能との間のデータ転送の関係。あなたが呼び出す関数内で関数を呼び出すときは、括弧内の関数名は、パラメータが「実パラメータ」と呼ばれた後、

簡単な例:

public static void main(String[] args) {
   ParamTest pt = new ParamTest();
   pt.sout("Hollis");//实际参数为 Hollis
}

public void sout(String name) { //形式参数为 name
   System.out.println(name);
}

実際のパラメータの参照メソッドが呼び出されたときに実際の送信の内容、パラメータ引数のコンテンツを受信するための仮パラメータ。

値は、参照によって渡され、渡された
実際のパラメータは、仮パラメータに渡される時、我々は、参照関数を呼び出すとき、上述します。しかし、プログラミング言語、両方の場合において、この転写工程の転送は、その値が渡され、参照によって渡されます。私たちは、プログラミング言語を見ては定義し、値のゾーンを提供し、参照渡しする方法です。

値の転送は、(値渡し)関数で変更パラメータは、実際のパラメータに影響を与えない場合、実際のパラメータは、そう、関数に渡された関数のコピーを呼び出すときをいいます。

参照渡して行う、それは機能の実際のパラメータに影響するパラメータを変更し、その後、関数を呼び出す際に、直接関数に渡される実引数に取り組むことを意味する(参照渡し)。

上記の概念では、あなたは、コードの最も簡単な一片出て、最終的には値渡しされるか、参照渡し、Javaのを見て、コードの練習を書くことができます。

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   int i = 10;
   pt.pass(i );
   System.out.println("print in main , i is " + i);
}

public void pass(int j) {
   j = 20;
   System.out.println("print in pass , j is " + j);
}

上記のコードは、我々は、パラメータの値は、それぞれの印刷方法とmainメソッドを渡し、処理パスでパラメータjの値を変更します。次のように出力結果があります

print in pass , j is 20
print in main , i is 10

可視、内部修飾は、メソッド名の値iが変化しないパラメータの実際の値を渡します。したがって、上記の定義によれば、それが結論でした:パスへのJavaの方法は値によって渡されます。

しかし、それはすぐに(ハハ、ほんの少しの結論にジャンプしないでください。)疑問視されました。その後、彼らは次のコードの外に移動します:

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   User hollis = new User();
   hollis.setName("Hollis");
   hollis.setGender("Male");
   pt.pass(hollis);
   System.out.println("print in main , user is " + hollis);
}

public void pass(User user) {
   user.setName("hollischuang");
   System.out.println("print in pass , user is " + user);
}

同じ方法は、パス方式のパラメータの値を変更するためのパス、同じです。出力:

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='hollischuang', gender='Male'}

上記で定義したパス実行の方法の後に、今変更される引数に、それは、パラメータの実際の値が変更され、参照によって渡され、それはまだ参照によって渡されません。したがって、コードの上記二枚によれば、新たな結論が得られた:オブジェクトの種類を基準に通過する際に、通常の転送タイプは、値によって渡されたJava方法。

しかし、この表現はまだ間違っています。私は、パラメータオブジェクトとして渡され、このパラメータの種類の下に見ることができるとは思いません。

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   String name = "Hollis";
   pt.pass(name);
   System.out.println("print in main , name is " + name);
}

public void pass(String name) {
   name = "hollischuang";
   System.out.println("print in pass , name is " + name);
}

上記のコードが出力されます

print in pass , name is hollischuang
print in main , name is Hollis

これは説明は何ですか?また、オブジェクトを渡しますが、パラメータの元の値が変更されていない、オブジェクトを渡さないと値が渡さなりましたか?

転送の値でJava
上では、我々は3つの例を挙げ、その結果は、初心者の多くにつながっている同じ性能ではない、とJavaの転送タイプのためにも、多くのシニアプログラマは、その理由を混同しています。

実際に、私は上記の概念は、問題のコードのほんの一例間違っていないことをお伝えしたいと思います。あなたがコンセプトの主なポイント、ポイントで、その後いくつかの実際のケースを描きに来て、私が来ます。

値の転送は、(値渡し)関数で変更パラメータは、実際のパラメータに影響を与えない場合、実際のパラメータは、そう、関数に渡された関数のコピーを呼び出すときをいいます。

参照渡して行う、それは機能の実際のパラメータに影響するパラメータを変更し、その後、関数を呼び出す際に、直接関数に渡される実引数に取り組むことを意味する(参照渡し)。

まあ、私はあなたが値が渡され、参照が転送イエスの違いに焦点を当てるものを、まとめる与えるでしょう。

我々は上記の見てきたパスのいくつかの例は、唯一の実際のパラメータが変更されたかどうか心配します。、我々は変化があったかどうかをチェックし、彼のname属性の値を変更しようとしているように、ユーザーオブジェクトが渡されました。実際には、実験方法が間違っている、もちろん、結論が問題になります。

なぜ実験方法を間違っていますか?ここでは、画像の一例を与えます。値が渡され、参照によって渡されているものの理解-深さを、是非、あなたはなぜ間違ったを知っています。

あなたの友人はあなたが参照渡しされ、彼に直接あなたの鍵を入れた場合、あなたの家に行きたいとき、あなたは鍵を持っています。彼はキーに彼の名前を刻まれたように、彼は何をした場合は、この場合には、このための鍵は、その後、独自のキーにあなたにこのキーバックは、より多くの彼の刻ま名外となります。

あなたの友人があなたの家に行きたいときにキーを持っていますか、あなたはまだ値によって渡され、彼自身の手で、彼に新しいキーを刻印しました。この場合、彼はこれはあなたの手でこのキーには影響しません何をキーに置きます。

しかし、関係なく、上記の例、あなたの友人があなたの家に、彼の鍵を取っ与える、ご自宅のテレビが激突します。そして、あなたが影響を受けることはないだろうと言いますか?我々は法の値を渡すときに、オブジェクトがないこと「大ヒットテレビ」で、それをユーザー名属性を変更することです。あなたは、キーが、家を開くためのキーを変更しないこと。

上記の例に例をとる。また、私たちは本当に何が起こるか見て、パラメータを変更しますか?

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   User hollis = new User();
   hollis.setName("Hollis");
   hollis.setGender("Male");
   pt.pass(hollis);
   System.out.println("print in main , user is " + hollis);
}

public void pass(User user) {
   user = new User();
   user.setName("hollischuang");
   user.setGender("Male");
   System.out.println("print in pass , user is " + user);
}

上記のコードでは、我々は次のように、ユーザオブジェクトが変更され、出力結果である方法を渡します。

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='Hollis', gender='Male'}

Javaが唯一の値によって渡される理由プロセス全体で何が起こっているかを見ては、その後、私はあなたを教えてあげましょう、のは、絵を描きましょう。

私たちは、メインの時間をユーザーオブジェクトを作成するときに、この数字を下げて少し説明、名前や性別などのデータを保持しているヒープメモリを、開きます。ホリスは、メモリアドレスは0x123456(図1)を保持します。

メソッド呼び出しを通過しようとすると、ユーザへのアドレスは0x123456は、この時点で、ユーザはこのアドレス(図2)を指すことができますときホリスは、ユーザの仮パラメータの実パラメータとして渡されたとき。

次に、パスメソッドのパラメータ、すなわち、ユーザ=新しいユーザー()に変更したとき、再オープンするユーザーに割り当てられたメモリの0X456789まで。ユーザの顔の後のすべての変更は、メモリは0x123456の内容(図3)を変更しないであろう。

この転送は、渡されたものを超えていますか?それは参照によって渡された場合、確かに、参照によって渡されない場合、ユーザーの実装では、新しいユーザー()=;実際の基準パラメータはなく、実際、0X456789を指すように変更されなければならない場合。

私たちが知ることができるという概念によって、ここでコピーの実パラメータのアドレスを参照するが、それは仮パラメータに渡されています。したがって、上記パラメータ値が実際に送信され、引数値としてオブジェクト参照のアドレスが仮パラメータに渡されます。

レッツ・レビューの例何が起こったかの例を見て、前に転送プロセスを「TVはヒット」。

同様に、伝送パラメータの間に、実際のパラメータ0X1213456アドレスは、パラメータ、しかし、この方法では、無修正パラメータ自体が、メモリに保持されている修飾されたアドレスパラメータにコピーされコンテンツ。

したがって、差分値が渡され、コンテンツ配信参照によって渡されません。しかし、最終的に仮パラメータのコピーすべき引数はありません。引数の内容を決定する際に使用すると、アドレスを渡すと渡す何を見て時間に影響を与えていないが、ある場合、このアドレスの変更を見て、代わりにオブジェクトを見ることで、影響を受けることはありませんが、アドレスの変化を指摘しました。キーと家との間の関係のように。

まあ、その場合には、なぜ上記の転送先、Stringオブジェクトのパフォーマンスの結果を提供し、ユーザーオブジェクトが同じにもされていないのですか?私たちは、パスメソッド名=「hollischuang」を使用します。名前の値を変更しようと、アドレスが誤って直接名の参照を変更しました。このコードは、新しい文字列になりますので、その後に相当し名への参照:

name = new String("hollischuang");

而原来的那个"Hollis"字符串还是由实参持有着的,所以,并没有修改到实际参数的值。

所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。

总结
无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递(call by sharing)。其实Java中的参数传递严格意义上说应该是按共享传递。

按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值)。在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作。如果该值在栈中,那么因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响。如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作。因为传递的是地址的拷贝所以函数内对值的操作对外部变量是可见的。

简单点说,Java中的传递,是值传递,而这个值,实际上是对象的引用。

而按共享传递其实只是按值传递的一个特例罢了。所以我们可以说Java的传递是按共享传递,或者说Java中的传递是值传递。

-----------------------------------本文转载自公众号 Hollis-----------------------------------------

おすすめ

転載: www.cnblogs.com/jichi/p/12031279.html