Java is Pass-by-Value, Dammit! 我靠!Java就是值传递!
Java is Pass-by-Value, Dammit! 我靠!Java就是值傳遞!
原文地址:http://javadude.com/articles/passbyvalue.htm
關(guān)鍵點(diǎn)
- 形如Object o這樣的定義,我們實(shí)際上定義一個(gè)指針
- 當(dāng)我們把此指針傳入方法形參,實(shí)則是把此指針?biāo)赶虻牡刂穫鬟f給了方法形參,而不是對(duì)象本體的傳入,也就是沒(méi)有進(jìn)行真正意義上的引用傳遞了。
全文翻譯
Introduction 引題
I finally decided to write up a little something about Java’s parameter passing. I’m really tired of hearing folks (incorrectly) state “primitives are passed by value, objects are passed by reference”.
我終于決定要寫(xiě)一點(diǎn)關(guān)于Java參數(shù)傳遞的東西了。我真的已經(jīng)厭倦人云亦云的觀點(diǎn)了——原始數(shù)據(jù)類型是值傳遞,對(duì)象是引用傳遞。
I’m a compiler guy at heart. The terms “pass-by-value” semantics and “pass-by-reference” semantics have very precise definitions, and they’re often horribly abused when folks talk about Java. I want to correct that… The following is how I’d describe these
我有一顆像編譯器樣的心。術(shù)語(yǔ)“值傳遞”和“引用傳遞”的語(yǔ)義是有嚴(yán)格定義的。然而在大眾談?wù)揓ava時(shí),這兩個(gè)術(shù)語(yǔ)總是遭到濫用。我想改變這種情況… 下面我就是我對(duì)此的解釋:
Pass-by-value 值傳遞
The actual parameter (or argument expression) is fully evaluated and the resulting value is copied into a location being used to hold the formal parameter’s value during method/function execution. That location is typically a chunk of memory on the runtime stack for the application (which is how Java handles it), but other languages could choose parameter storage differently.
實(shí)參(或者變量表達(dá)式)已被完整計(jì)算,并且結(jié)果值被復(fù)制到了方法(或函數(shù))執(zhí)行時(shí)負(fù)責(zé)持有形參值的地方。這個(gè)地方通常是應(yīng)用運(yùn)行時(shí)棧的一塊內(nèi)存區(qū)域(Java就是這么處理的),但是其他語(yǔ)言可以選擇別的參數(shù)存儲(chǔ)方式。
Pass-by-reference 引用傳遞
The formal parameter merely acts as an alias for the actual parameter. Anytime the method/function uses the formal parameter (for reading or writing), it is actually using the actual parameter.
形參僅僅為實(shí)參扮演了一個(gè)別名的角色。任何時(shí)候,當(dāng)方法(或函數(shù))使用這些形參(為了讀寫(xiě)),它實(shí)際上就是在使用實(shí)參。
Java is strictly pass-by-value, exactly as in C. Read the Java Language Specification (JLS). It’s spelled out, and it’s correct. Inhttp://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.1:
Java是嚴(yán)格意義上的值傳遞,如C一樣。閱讀下《Java語(yǔ)言規(guī)范》。其中對(duì)此已經(jīng)講的很清楚了這是正確的。原文如下:
When the method or constructor is invoked (�15.12), the?values?of the actual argument expressions initialize newly created parameter variables, each of the declared Type, before execution of the body of the method or constructor. The Identifier that appears in the DeclaratorId may be used as a simple name in the body of the method or constructor to refer to the formal parameter.
當(dāng)一個(gè)方法或構(gòu)造器被調(diào)用時(shí),實(shí)參表達(dá)式的值會(huì)在執(zhí)行方法或構(gòu)造器的代碼塊前,初始化剛剛創(chuàng)建的參數(shù)變量,以及每個(gè)聲明的類型。在方法或構(gòu)造器的代碼塊中,DeclaratorID中出現(xiàn)的Identifier或許會(huì)作為一個(gè)簡(jiǎn)單的名字,從而去引用一個(gè)形參。
In the above,?values?is my emphasis, not theirs
上文中對(duì)值的加粗是我自己加的,不是原文的
In short: Java has pointers and is strictly pass-by-value. There’s no funky rules. It’s simple, clean, and clear. (Well, as clear as the evil C++-like syntax will allow ;)
簡(jiǎn)言之:Java具有指針,并且是嚴(yán)格意義上的值傳遞。沒(méi)有其他雜七雜八的規(guī)定,就是這么簡(jiǎn)單、清晰、明了。(這就同類似邪惡C++的語(yǔ)法所允許的那樣一樣清晰;)
Note: See the note at the end of this article for the semantics of remote method invocation (RMI). What is typically called “pass by reference” for remote objects is actually incredibly bad semantics.
注意:請(qǐng)關(guān)注文章結(jié)尾處關(guān)于“遠(yuǎn)程方法調(diào)用”的文章。遠(yuǎn)程對(duì)象中所謂的“引用傳遞”的概念實(shí)際上是完全錯(cuò)誤的。
The Litmus Test 立見(jiàn)分曉的測(cè)試
There’s a simple “l(fā)itmus test” for whether a language supports pass-by-reference semantics:
這里有個(gè)簡(jiǎn)單的“石蕊測(cè)試(譯者注:一個(gè)比喻,指此測(cè)試可以像石蕊試紙那樣立刻看到結(jié)果)”,它可應(yīng)用于任何支持引用傳遞的語(yǔ)言:
Can you write a traditional swap(a,b) method/function in the language?
你可以在此語(yǔ)言環(huán)境下寫(xiě)出一個(gè)標(biāo)準(zhǔn)的swap(a,b)方法(函數(shù))嘛?
A traditional swap method or function takes two arguments and swaps them such that variables passed into the function are changed outside the function. Its basic structure looks like
一個(gè)標(biāo)準(zhǔn)的swap方法(函數(shù))有兩個(gè)參數(shù),它會(huì)將這兩者互換。這樣,傳入方法里面的變量就可以改變方法外變量的值。它的基本結(jié)構(gòu)如下:
// Figure 1: (Non-Java) Basic swap function structureswap(Type arg1, Type arg2) {
Type temp = arg1;
arg1 = arg2;
arg2 = temp;
}
If you can write such a method/function in your language such that calling
如果你可以在你語(yǔ)言環(huán)境下寫(xiě)出這樣的方法(函數(shù)),那么這樣的調(diào)用
// Figure 2: (Non-Java) Calling the swap functionType var1 = ...;
Type var2 = ...;
swap(var1,var2);
actually switches the values of the variables var1 and var2, the language supports pass-by-reference semantics.
就會(huì)從實(shí)際上交換變量var1和var2的值。前提是需要此語(yǔ)言支持引用傳遞
For example, in Pascal, you can write
例如,在Pascal中,你可以這樣寫(xiě)
//Figure 3: (Pascal) Swap functionprocedure swap(var arg1, arg2: SomeType);
var
temp : SomeType;
begin
temp := arg1;
arg1 := arg2;
arg2 := temp;
end;
...
{ in some other procedure/function/program }
var
var1, var2 : SomeType;
begin
var1 := ...; { value "A" }
var2 := ...; { value "B" }
swap(var1, var2);
{ now var1 has value "B" and var2 has value "A" }
end;
or in C++ you could write
或者在C++中你可以這樣寫(xiě)
//Figure 4: (C++) Swap functionvoid swap(SomeType& arg1, Sometype& arg2) {
SomeType temp = arg1;
arg1 = arg2;
arg2 = temp;
}
...
SomeType var1 = ...; // value "A"
SomeType var2 = ...; // value "B"
swap(var1, var2); // swaps their values!
// now var1 has value "B" and var2 has value "A"
(Please let me know if my Pascal or C++ has lapsed and I’ve messed up the syntax…)
(請(qǐng)讓我知道我的Pascal和C++程序?qū)Σ粚?duì),我已經(jīng)搞混兩者的語(yǔ)法了>_<)
But you cannot do this in Java!
但是你在Java中做不到!
Now the details… 現(xiàn)在看細(xì)節(jié)
The problem we’re facing here is statements like
我們面對(duì)的問(wèn)題就是類似下面這樣的陳述:
In Java, Objects are passed by reference, and primitives are passed by value.
在Java中,對(duì)象是通過(guò)引用傳遞的,基本數(shù)據(jù)類型是值傳遞的
This is half incorrect. Everyone can easily agree that primitives are passed by value; there’s no such thing in Java as a pointer/reference to a primitive.
這句話是半對(duì)的。人們都愿意承認(rèn)非原始數(shù)據(jù)類型是值傳遞的;Java中沒(méi)有這樣一種指針(或引用)指向一個(gè)原始數(shù)據(jù)類型。
However, Objects are not passed by reference. A correct statement would be Object references are passed by value.
然而,對(duì)象也并非是引用傳遞的。正確的說(shuō)法是對(duì)象引用是值傳遞的。
This may seem like splitting hairs, but it is far from it. There is a world of difference in meaning. The following examples should help make the distinction.
看起來(lái)有些斤斤計(jì)較,但是并非如此。這一個(gè)充滿不同解釋的世界。下面的例子將有助于區(qū)分上面的概念。
In Java, take the case of
在Java中,我們以此為例:
//Figure 5: (Java) Pass-by-value examplepublic void foo(Dog d) {
d = new Dog("Fifi"); // creating the "Fifi" dog
}
Dog aDog = new Dog("Max"); // creating the "Max" dog
// at this point, aDog points to the "Max" dog
foo(aDog);
// aDog still points to the "Max" dog
the variable passed in (aDog) is not modified! After calling foo, aDog still points to the “Max” Dog!
傳入的變量(即 aDog)并沒(méi)有被修改!,在調(diào)用foo方法后,aDog依舊指向“Max”Dog對(duì)象!
Many people mistakenly think/state that something like
很多人像這樣錯(cuò)誤的認(rèn)為(或陳述)這樣的東西:
//Figure 6: (Java) Still pass-by-value...public void foo(Dog d) {
d.setName("Fifi");
}
shows that Java does in fact pass objects by reference.
表明了Java事實(shí)上是通過(guò)引用傳遞對(duì)象的。
The mistake they make is in the definition of
他們犯的錯(cuò)誤在于對(duì)下面定義代碼的理解
// Figure 7: (Java) Defining a Dog pointerDog d;
itself. When you write that definition, you are defining a pointer to a Dog object, not a Dog object itself.
當(dāng)你寫(xiě)下這樣的定義時(shí),你就會(huì)創(chuàng)建了一個(gè)指向Dog對(duì)象的指針,而非一個(gè)Dog對(duì)象本身。
On Pointers versus References… 指針和引用的對(duì)比
The problem here is that the folks at Sun made a naming mistake.
問(wèn)題在于Sun公司的家伙們制造了一個(gè)命名錯(cuò)誤。
In programming language design, a “pointer” is a variable that indirectly tracks the location of some piece of data. The value of a pointer is often the memory address of the data you’re interested in. Some languages allow you to manipulate that address; others do not.
在編程語(yǔ)言的設(shè)計(jì)中,一個(gè)“指針”是一種變量。它間接追蹤某些數(shù)據(jù)的位置。一個(gè)指針的值通常是你所感興趣的數(shù)據(jù)的內(nèi)存地址。一些語(yǔ)言允許你操縱這個(gè)地址,其他則非也。
A “reference” is an alias to another variable. Any manipulation done to the reference variable directly changes the original variable.
一個(gè)“引用”則是另一個(gè)變量的別名。任何對(duì)此引用的操作都將直接改變?cè)甲兞俊?/p>
Check out the second sentence ofhttp://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1.
看下這個(gè)網(wǎng)址的第二句話
“The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object”
引用的值(或者說(shuō)就是引用)是這些對(duì)象的指針。而一個(gè)特別的空引用,它不指向任何對(duì)象
They emphasize “pointers” in their description… Interesting…
他們?cè)谒麄兊年愂鲋袕?qiáng)調(diào)了“指針”一詞,挺有意思~
When they originally were creating Java, they had “pointer” in mind (you can see some remnants of this in things like?
NullPointerException).
當(dāng)他們?cè)趧?chuàng)作Java之初時(shí),他們的腦海中是有“指針”這個(gè)概念的(你可以看到一些殘存的跡象,如空指針異常)。
Sun wanted to push Java as a secure language, and one of Java’s advantages was that it does not allow pointer arithmetic as C++ does.
Sun公司希望把Java做成一個(gè)安全語(yǔ)音,并且Java優(yōu)勢(shì)之一就是它不允許像C++那樣的指針運(yùn)算。
They went so far as to try a different name for the concept, formally calling them “references”. A big mistake and it’s caused even more confusion in the process.
他們努力為此概念嘗試使用一個(gè)不同名稱,并在最終正式稱其為“引用”。這是一個(gè)大失誤,并且這在后來(lái)制造了更多的困惑。
There’s a good explanation of reference variables athttp://www.cprogramming.com/tutorial/references.html. (C++ specific, but it says the right thing about the concept of a reference variable.)
這個(gè)網(wǎng)址中有對(duì)引用變量的不錯(cuò)的解釋。(雖然針對(duì)C++,但是它正確解釋了引用變量的相關(guān)概念)
The word “reference” in programming language design originally comes from how you pass data to subroutines/functions/procedures/methods. A reference parameter is an alias to a variable passed as a parameter.
“引用”一詞在編程語(yǔ)言設(shè)計(jì)中,最初來(lái)源于如何向子程序、函數(shù)、過(guò)程或方法傳數(shù)據(jù)。一個(gè)引用參數(shù)是一個(gè)作為參數(shù)傳遞的變量的別名。
In the end, Sun made a naming mistake that’s caused confusion. Java has pointers, and if you accept that, it makes the way Java behaves make much more sense.
最后,Sun也就犯了一個(gè)命名錯(cuò)誤,并且這個(gè)錯(cuò)誤引起了不少困惑。Java具有指針,并且如果接受這個(gè)現(xiàn)實(shí),這就會(huì)讓Java變得更有意義了。
Calling Methods 方法調(diào)用
Calling
調(diào)用
//Figure 8: (Java) Passing a pointer by valuefoo(d);
passes the?value of d?to foo; it does not pass the object that d points to!
這個(gè)方法時(shí),會(huì)將d的值傳入到foo中;它并不會(huì)傳入d所指向的對(duì)象
The value of the pointer being passed is similar to a memory address. Under the covers it may be a tad different, but you can think of it in exactly the same way. The value uniquely identifies some object on the heap.
指針?biāo)鶄魅氲闹殿愃苾?nèi)存地址。在底層中,兩者有微小差別,但是你可認(rèn)為兩者完全相同。指針的值唯一標(biāo)識(shí)堆中的一些對(duì)象。
However, it makes no difference how pointers are?implemented?under the covers. You program with them?exactly?the same way in Java as you would in C or C++. The syntax is just slightly different (another poor choice in Java’s design; they should have used the same -> syntax for de-referencing as C++).
然而,這不耽誤指針在底層的實(shí)現(xiàn)。在Java編程中,你可以完全像C或C++那樣使用指針。就是語(yǔ)法上有點(diǎn)滴的不同(這又是Java設(shè)計(jì)中的一個(gè)軟肋;設(shè)計(jì)者們本應(yīng)像C++那樣使用“->”作為解引用語(yǔ)法)
In Java,
在Java中,
//Figure 9: (Java) A pointerDog d;
is?exactly?like C++’s
完全像C++中的
//Figure 10: (C++) A pointerDog *d;
And using
指針的使用
//Figure 11: (Java) Following a pointer and calling a methodd.setName("Fifi");
is exactly like C++’s
完全像C++的
//Figure 12: (C++) Following a pointer and calling a methodd->setName("Fifi");
To sum up: Java?has?pointers, and the?value?of the pointer is passed in. There’s no way to actually pass an object itself as a parameter. You can only pass a?pointer?to an object.
總結(jié)下:Java有指針,并且傳入的是指針的值。無(wú)法傳入一個(gè)對(duì)象本身作為參數(shù)。你僅可以向?qū)ο髠魅胍粋€(gè)指針。
Keep in mind, when you call
記住,當(dāng)你調(diào)用
//Figure 13: (Java) Even more still passing a pointer by valuefoo(d);
you’re not passing an object; you’re passing a pointer to the object.
時(shí),你不是在傳一個(gè)對(duì)象實(shí)體,而是在傳入對(duì)象的一個(gè)指針。
For a slightly different (but still correct) take on this issue, please seehttp://www-106.ibm.com/developerworks/library/j-praxis/pr1.html. It’s from Peter Haggar’s excellent book, Practical Java.)
對(duì)于此問(wèn)題的一個(gè)輕微的不同之處(但是依舊是正確的),請(qǐng)參閱網(wǎng)址內(nèi)容。內(nèi)陸來(lái)自Peter hagger的一本經(jīng)典之作《Practical Java》
A Note on Remote Method Invocation (RMI) 一條關(guān)于遠(yuǎn)程方法調(diào)用的筆記
When passing parameters to remote methods, things get a bit more complex. First, we’re (usually) dealing with passing data between two independent virtual machines, which might be on separate physical machines as well. Passing the value of a pointer wouldn’t do any good, as the target virtual machine doesn’t have access to the caller’s heap.
當(dāng)向遠(yuǎn)程方法傳參數(shù)時(shí),會(huì)稍微有點(diǎn)麻煩。首先,我們(經(jīng)常)在兩個(gè)獨(dú)立的虛擬機(jī)間傳送數(shù)據(jù),或許也同時(shí)在不同物理機(jī)間。傳送一個(gè)指針的值不會(huì)是個(gè)好的選項(xiàng),因?yàn)槟繕?biāo)虛擬機(jī)無(wú)法訪問(wèn)調(diào)用者的堆。
You’ll often hear “pass by value” and “pass by reference” used with respect to RMI. These terms have more of a “l(fā)ogical” meaning, and really aren’t correct for the intended use.
你會(huì)在遠(yuǎn)程方法調(diào)用中常常聽(tīng)到值傳遞和引用傳遞。這些術(shù)語(yǔ)具有比邏輯上更加廣泛的意義,并且對(duì)于將要使用的場(chǎng)景而言,這些術(shù)語(yǔ)實(shí)際上并不準(zhǔn)確。
Here’s what is usually meant by these phrases with regard to RMI. Note that this is not proper usage of “pass by value” and “pass by reference” semantics:
這里給出與遠(yuǎn)程方法調(diào)用RMI相關(guān)術(shù)語(yǔ)的常用意義。注意,這并非嚴(yán)格意義上的“值傳遞”和“引用傳遞”語(yǔ)義:
RMI Pass-by-value 遠(yuǎn)程方法調(diào)用之值傳遞
The actual parameter is serialized and passed using a network protocol to the target remote object. Serialization essentially “squeezes” the data out of an object/primitive. On the receiving end, that data is used to build a “clone” of the original object or primitive. Note that this process can be rather expensive if the actual parameters point to large objects (or large graphs of objects).
實(shí)參被序列化,并利用網(wǎng)絡(luò)協(xié)議傳送到遠(yuǎn)程目標(biāo)對(duì)象。序列化本質(zhì)上從一個(gè)對(duì)象(或原始數(shù)據(jù)類型)中“壓榨”出數(shù)據(jù)。在接收完畢后,數(shù)據(jù)會(huì)被用于創(chuàng)建原有對(duì)象(或原始數(shù)據(jù)類型)的“克隆”。注意如果實(shí)參指向了一個(gè)大對(duì)象(或者大對(duì)象圖),這項(xiàng)操作的代價(jià)將會(huì)非常巨大。
This isn’t quite the right use of “pass-by-value”; I think it should really be called something like “pass-by-memento”. (See “Design Patterns” by Gamma et al for a description of the Memento pattern).
這并非完全正確地使用了值傳遞;我個(gè)人認(rèn)為這應(yīng)該被稱為一種類似“記憶傳遞”的東西。(更多內(nèi)容,請(qǐng)參閱Gamma等人編著的《設(shè)計(jì)模式》中關(guān)于記憶模式的表述)
RMI Pass-by-reference 遠(yuǎn)程方法調(diào)用之引用傳遞
The actual parameter, which is itself a remote object, is represented by a proxy. The proxy keeps track of where the actual parameter lives, and anytime the target method uses the formal parameter, another remote method invocation occurs to “call back” to the actual parameter. This can be useful if the actual parameter points to a large object (or graph of objects) and there are few call backs.
本身是一個(gè)遠(yuǎn)程對(duì)象的實(shí)參是通過(guò)代理來(lái)表示的。代理會(huì)追蹤實(shí)參存活的地點(diǎn),以及目標(biāo)方法使用形參,或另一個(gè)遠(yuǎn)程方法回調(diào)時(shí),觸發(fā)對(duì)這個(gè)實(shí)參的回調(diào)的任何時(shí)刻。用代理這種方法在一個(gè)實(shí)參指向了大對(duì)象(或大對(duì)象圖)時(shí)會(huì)非常有用,并且回調(diào)也會(huì)很少。
This isn’t quite the right use of “pass-by-reference” (again, you cannot change the actual parameter itself). I think it should be called something like “pass-by-proxy”. (Again, see “Design Patterns” for descriptions of the Proxy pattern).
這并非是對(duì)“引用傳遞”完全正確的使用(再一次強(qiáng)調(diào),你無(wú)法改變實(shí)參本身)。我認(rèn)為這樣叫做“代理傳遞”樣的東西(再次推薦閱讀《設(shè)計(jì)模式》中對(duì)代理模式的講解)
Follow up from stackoverflow.com 在stackoverflow.com上跟進(jìn)問(wèn)題
I posted the following as some clarification when a discussion on this article arose on?http://stackoverflow.com.
當(dāng)在stackoverflow上討論此文時(shí),我貼出了如下內(nèi)容以作說(shuō)明:
The Java Spec says that everything in java is pass-by-value. There is no such thing as “pass-by-reference” in java.
《Java規(guī)范》說(shuō)Java中的任何傳遞都是值傳遞。在Java中沒(méi)有“引用傳遞”一說(shuō)。
The key to understanding this is that something like
理解此的關(guān)鍵,就是要理解下面這樣的代碼:
//Figure 14: (Java) Not a Dog; a pointer to a DogDog myDog;
is not a Dog; it’s actually a pointer to a Dog.
并不代表一個(gè)Dog對(duì)象;它實(shí)際上是執(zhí)行Dog對(duì)象的的一個(gè)指針。
What that means, is when you have
它表達(dá)的意思是,當(dāng)你有
// Figure 15: (Java) Passing the Dog's locationDog myDog = new Dog("Rover");
foo(myDog);
you’re essentially passing the address of the created Dog object to the foo method. (I say essentially b/c java pointers aren’t direct addresses, but it’s easiest to think of them that way)
實(shí)際上你正在向foo方法中傳遞創(chuàng)建的Dog對(duì)象的地址。(我認(rèn)為本質(zhì)上Java指針并非是直接地址,但是這么想會(huì)讓理解更容易一些)
Suppose the Dog object resides at memory address 42. This means we pass 42 to the method.
假設(shè)Dog對(duì)象駐扎在內(nèi)存地址42中。這意味著我們向方法傳入42。
If the Method were defined as
如果這個(gè)方法沒(méi)定義成這樣
//Figure 16: (Java) Looking at the called method in detailpublic void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
Let’s look at what’s happening.
讓我們看看這會(huì)發(fā)生什么。
the parameter someDog is set to the value 42
參數(shù)someDog被設(shè)置為42。
at line “AAA” 在“AAA”行
someDog is followed to the Dog it points to (the Dog object at address 42) that Dog (the one at address 42) is asked to change his name to Max
someDog指向這個(gè)Dog對(duì)象(也就是在地址42中存儲(chǔ)的Dog對(duì)象),并且這個(gè)對(duì)象要求將名字改為Max。
at line “BBB” 在“BBB”行
a new Dog is created. Let’s say he’s at address 74 we assign the parameter someDog to 74
一個(gè)新的Dog對(duì)象被創(chuàng)建。讓我們假設(shè)它在內(nèi)存地址74當(dāng)中。我們將74傳入someDog對(duì)象中。
at line “CCC” 在“CCC”行
someDog is followed to the Dog it points to (the Dog object at address 74) that Dog (the one at address 74) is asked to change his name to Rowlf then, we return
someDog現(xiàn)在指向了地址為74的Dog對(duì)象,現(xiàn)在這個(gè)位于地址74的Dog對(duì)象要求將名字改為Rowlf,然后我們的方法返回了。
Now let’s think about what happens outside the method:
現(xiàn)在讓我們想想在方法外發(fā)生了啥:
Did myDog change? myDog發(fā)生改變了嘛?
There’s the key.
這是關(guān)鍵。
Keeping in mind that myDog is a pointer, and not an actual Dog, the answer is NO. myDog still has the value 42; it’s still pointing to the original Dog.
記住myDog 是一個(gè)指針,并非一個(gè)真實(shí)的Dog對(duì)象。答案是“沒(méi)有”。myDog依舊是42;依然指向了原來(lái)的Dog對(duì)象。
It’s perfectly valid to follow an address and change what’s at the end of it; that does not change the variable, however.
追蹤一個(gè)地址并在最后改變其內(nèi)容是完全可以的;然而變量本身并沒(méi)有被改變。
Java works exactly like C. You can assign a pointer, pass the pointer to a method, follow the pointer in the method and change the data that was pointed to. However, you cannot change where that pointer points.
Java 非常像C。你可以為一個(gè)指針賦值,也可把指針傳入到一個(gè)方法中去,還可以使用方法中的指針改變它所指向的內(nèi)容。然而,你無(wú)法改變指針的指向。
In C++, Ada, Pascal and other languages that support pass-by-reference, you can actually change the variable that was passed.
在C++,Ada,Pascal以及其他支持引用傳遞的語(yǔ)言中,你可以對(duì)傳入的變量進(jìn)行實(shí)際上的改變。
If Java had pass-by-reference semantics, the foo method we defined above would have changed where myDog was pointing when it assigned someDog on line BBB.
如果Java支持“引用傳遞”的概念,那么我們?cè)谏厦娑x的這個(gè)foo方法將會(huì)在BBB行,當(dāng)我們把它賦值給someDog時(shí),改變myDog的指向。
Think of reference parameters as being aliases for the variable passed in. When that alias is assigned, so is the variable that was passed in.
想想作為傳入變量別名的引用參數(shù)。當(dāng)我們分配這個(gè)別名時(shí),那么這個(gè)別名實(shí)際上就是指我們傳入的變量。
總結(jié)
以上是生活随笔為你收集整理的Java is Pass-by-Value, Dammit! 我靠!Java就是值传递!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言-数学运算
- 下一篇: word pdf 互转