Heim >Java >javaLernprogramm >Warum wird der Wert nur in Java übergeben?
Wird die Parameterübergabe in Java als Wert oder als Referenz übergeben? Diese Frage ist sehr einfach, aber viele Leute sind etwas verwirrt
Zuerst müssen wir verschiedene Konzepte über Parameter verstehen
Formale Parameter: Parameter, die beim Definieren einer Funktion zum Empfang eingehender Funktionen verwendet werden Parameter, Wenn wir beispielsweise eine Funktion schreiben, sind die Parameter in der Funktion formale Parameter
public void test(String str) { //str为形式参数 System.out.println(str); }
Tatsächliche Parameter:Wenn wir eine Funktion aufrufen, werden die Parameter in Klammern nach dem Funktionsnamen als tatsächliche Parameter bezeichnet und müssen einen bestimmten Wert haben. Wie im Beispiel unten gezeigt. Wie in
public static void main(String[] args) { A a = new A(); a.test("小 明"); //"小 明"则为实际参数 }
gezeigt, können wir feststellen, dass beim Aufruf einer parametrisierten Funktion die tatsächlichen Parameter an die formalen Parameter übergeben werden.
Im Allgemeinen gibt es zwei Situationen für Parameter in diesem Übergabeprozess: Wertübergabe und Referenzübergabe.
Wertübergabe: Kopieren Sie beim Aufrufen einer Funktion die tatsächlichen Parameter und übergeben Sie sie an die Funktion. Das Ändern der Parameter innerhalb der Funktion hat keine Auswirkungen auf die tatsächlichen Parameter, d. h. erstellt eine Kopie und hat keine Auswirkungen auf die natives Objekt
keine Kopie erstellt, es wirkt sich auf das native Objekt aus
Basisdatentypen und Referenzdatentypen, mit Ausnahme von 8 Basisdatentypen , sie sind alle Referenzdatentypen, nämlich byte, short , int, long, char, boolean, float, double
byte,short,int,long,char,boolean,float,double
对于这个问题,我们先来看几个例子慢慢道来:
public class TestBasic { public static void main(String[] args) { int num1 = 10; int num2 = 20; change(num1, num2); System.out.println("=============="); System.out.println("num1 = " + num1); System.out.println("num2 = " + num2); } public static void change(int param1, int param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1 = 333; param2 = 444; System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
结果:
param1 = 10
param2 = 20
after change....
param1 = 333
param2 = 444
==============
num1 = 10
num2 = 20
我们可以发现,change()方法内对变量重新赋值,并未改变变量num1和num2的值,改变的只是change()方法内的num1和num2的副本。我们需要知道,基本数据类型在内存中只有一块存储空间,分配在栈stack中。
Java传参的类型如果是基本数据类型,是值传递。
public class TestQuote { public static void main(String[] args) { String str = "小明"; StringBuilder str2 = new StringBuilder("今天天气好"); change(str,str2); System.out.println("=============="); System.out.println("str = " + str); System.out.println("str2 = " + str2); } public static void change(String param1,StringBuilder param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1= "小张"; param2.append(",我们去钓鱼"); System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
结果:
param1 = 小明
param2 = 今天天气好
after change....
param1 = 小张
param2 = 今天天气好,我们去钓鱼
str = 小明
str2 = 今天天气好,我们去钓鱼
我们发现str变量没有改变,但是str2变量却改变了,大家是不是迷惑了:Java传参的类型如果是引用数据类型,是值传递还是引用传递?
其实大家被一堆术语给忽悠了,笔者画了2张图,帮助大家理解:
before change():
after change():
在Java中,除了基本数据类型以外,其他的都是引用类型,引用类型在内存中有两块存储空间(一块在栈stack中,一块在堆heap中)。
如果参数是引用类型,传递的就是实参所引用的对象在栈中地址值的拷贝,这里创建的副本是 地址的拷贝。那就有人说了,可是它值变了呀,这明明就是"引用传递"嘛?
我们可以换个角度理解,如果我们把栈地址当成值,会创建栈地址副本(复制栈帧),栈地址最终并没有改变,改变的是堆内存中的值。这就好比栈地址是钥匙,我们copy了一把,它能打开保险箱。我们关心的是钥匙有没有花纹这种变化,至于打开保险箱后的钱多钱少,我们并不需要关心。
虽然调用完函数后,str2变量值(堆中的数据)改变了,但是参数是引用类型,传递的实参是 栈中地址值,这是我们关心的,拷贝的是栈中地址值,最终栈中地址值并没有改变。所以是符合值传递的定义创建副本,不会影响原生对象。
可能又有人问了,那str变量值为啥没有改变呢?其实这完全是由于String类
Wird Java als Wert oder als Referenz übergeben?
🎜param1 = 10🎜Wir können feststellen, dass die Neuzuweisung von Variablen in der Methode change() die Werte der Variablen num1 und num2 nicht ändert. 🎜Was sich ändert, sind nur die Kopien von num1 und num2 in der Methode change(). 🎜Wir müssen wissen, dass grundlegende Datentypen nur einen Speicherplatz im Speicher haben, der im 🎜Stapel🎜 zugewiesen ist. 🎜🎜Wenn der in Java übergebene Parametertyp ein Basisdatentyp ist, wird er 🎜als Wert übergeben🎜. 🎜🎜🎜
param2 = 20
nach Änderung ....
param1 = 333
param2 = 444
==============
num1 = 10
num2 = 20🎜
🎜param1 = Xiao Ming🎜Wir haben festgestellt, dass sich die str-Variable nicht geändert hat, aber die Die str2-Variable hat sich geändert. Sind Sie verwirrt: Wenn der in Java übergebene Parametertyp ein Referenzdatentyp ist, handelt es sich dann um „Übergabe per Wert“ oder „Übergabe per Referenz“? 🎜🎜Tatsächlich hat sich jeder von einer Reihe von Begriffen täuschen lassen, um allen das Verständnis zu erleichtern: 🎜🎜vor der Änderung():🎜🎜🎜🎜after change():🎜🎜🎜🎜In Java sind mit Ausnahme der Basisdatentypen alle anderen Referenztypen. Referenztypen verfügen über zwei Speicherplätze im Speicher (einen im Stapel und einen im Heap). 🎜🎜Wenn der Parameter ein Referenztyp ist, wird eine Kopie des Adresswerts des Objekts übergeben, auf das der tatsächliche Parameter auf dem Stapel verweist. Die hier erstellte Kopie ist eine Kopie der Adresse. Dann hat es jemand gesagt, aber sein Wert hat sich geändert. Handelt es sich offensichtlich um eine „Weitergabe als Referenz“? 🎜🎜Wir können es aus einer anderen Perspektive verstehen. Wenn wir die Stapeladresse als Wert behandeln, wird eine Kopie der Stapeladresse erstellt (kopieren Sie den Stapelrahmen), aber der Wert in Der Heap-Speicher ändert sich. Es ist, als wäre die Stapeladresse ein Schlüssel. Wenn wir sie kopieren, kann sie den Safe öffnen. Was uns interessiert, ist, ob sich das Muster des Schlüssels ändert. Was den Geldbetrag nach dem Öffnen des Safes betrifft, ist uns das egal. 🎜🎜Obwohl sich der Wert der str2-Variablen (Daten im Heap) nach dem Aufruf der Funktion geändert hat, handelt es sich bei dem Parameter um einen Referenztyp, und der tatsächlich übergebene Parameter ist der Adresswert im Stapel kopiert ist der Adresswert im Stapel. Der endgültige Adresswert auf dem Stapel hat sich nicht geändert. Daher entspricht das Erstellen einer Kopie der Definition von „Wertübertragung“ und hat keine Auswirkungen auf das Originalobjekt. 🎜🎜Jemand fragt sich vielleicht noch einmal: Warum ändert sich der Wert der Str-Variablen nicht? Tatsächlich liegt dies ausschließlich an der besonderen Natur der
param2 = Das heutige Wetter ist gut
nach der Änderung....
param1 = Xiao Zhang
param2 = Das heutige Wetter Okay, lass uns angeln gehen
str = Xiao Ming
str2 = Das Wetter ist heute gut, lass uns angeln gehen🎜
String-Klasse
. Wir wissen, dass sie zu diesem Zeitpunkt unveränderlich und endgültig ist Objekt implizit und gleichzeitig Ein neuer Speicherplatz wird im Heap-Speicher geöffnet, und param1 zeigt auf diesen neu geöffneten Speicherplatz. Es gibt keine Änderung an den Daten im Heap-Speicherbereich, auf den die ursprüngliche Adresse str zeigt. 🎜Das obige ist der detaillierte Inhalt vonWarum wird der Wert nur in Java übergeben?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!