※ 引述《qrtt1 (thinking in java)》之銘言:
: java的傳值對原生型態來說是call by value
: 型態多大產生多大的副本
: 對reference來說,不是傳副本。
: 是reference alias,是別名
: 所以不管原物件多大,都增加一個reference的大小
根據在JLS中的定義中,Java只有call by value
而傳reference type時,就是把那個reference value複製
所以也是傳副本,其實與傳primitive types沒有差異
(reference value一詞在JLS 4.1中出現)
用到"reference alias",我認為反而會容易讓人混亂,
會讓人認為是原本的reference的alias (reference's alias)
因為根據"alias"這個字的意思,就是你對這個東西動作等同於對原本的
那這樣一來你在method中對傳進來的東西做下面的事
obj.method(x); //某個地方call了下面這個method
------------------------------------------------
public void method(Object y) {
y = null; //若此y是前面x的alias,
//那麼在y上的動作等於在x上
}
會讓人誤以為會把原始的argument設為null
我想要說的只是,使用"alias"這個字很容易讓人誤解
我在google查了"alias"這個字的意思,但找不到簡單明瞭的解釋
所以我就拿C++ Primer中對alias的描述
"A reference is an Alias"
"Because a reference is just another name for the object to which
it is bound, all operations on a reference are actually operations on
the underlying object to which the reference is bound."
(此處object代表東西,不是我們一般Java認知的物件)
雖然在C++與Java中的reference不盡相同,但其中可以看出
alias這個詞就是等同於對原本的"underlying object"動作,
所以如果依此去解釋"傳reference type時就是傳reference alias"
那麼就會出現上面這種錯誤的推論了~
我的建議是,盡量使用JLS中所用的詞,因為Java與C++有些東西同名不同義
在討論時容易造成誤解,其實Java的行為是比較簡單,總之就是call by value
什麼都是傳副本,只是看你今天要傳的是"primitive value"的副本,
還是"reference value"的副本。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.121.212.1
> -------------------------------------------------------------------------- <
作者: qrtt1 (thinking in java) 看板: java
標題: Re: [問題] 問一個 記憶體 和 GC 的問題
時間: Tue Jan 31 23:25:44 2006
※ 引述《jackyhuang (雪.狼.湖)》之銘言:
: ※ 引述《qrtt1 (thinking in java)》之銘言:
: : java的傳值對原生型態來說是call by value
: : 型態多大產生多大的副本
: : 對reference來說,不是傳副本。
: : 是reference alias,是別名
: : 所以不管原物件多大,都增加一個reference的大小
: 根據在JLS中的定義中,Java只有call by value
: 而傳reference type時,就是把那個reference value複製
: 所以也是傳副本,其實與傳primitive types沒有差異
: (reference value一詞在JLS 4.1中出現)
: 用到"reference alias",我認為反而會容易讓人混亂,
: 會讓人認為是原本的reference的alias (reference's alias)
: 因為根據"alias"這個字的意思,就是你對這個東西動作等同於對原本的
: 那這樣一來你在method中對傳進來的東西做下面的事
: obj.method(x); //某個地方call了下面這個method
: ------------------------------------------------
: public void method(Object y) {
: y = null; //若此y是前面x的alias,
: //那麼在y上的動作等於在x上
: }
: 會讓人誤以為會把原始的argument設為null
: 我想要說的只是,使用"alias"這個字很容易讓人誤解
: 我在google查了"alias"這個字的意思,但找不到簡單明瞭的解釋
: 所以我就拿C++ Primer中對alias的描述
: "A reference is an Alias"
: "Because a reference is just another name for the object to which
: it is bound, all operations on a reference are actually operations on
: the underlying object to which the reference is bound."
: (此處object代表東西,不是我們一般Java認知的物件)
: 雖然在C++與Java中的reference不盡相同,但其中可以看出
: alias這個詞就是等同於對原本的"underlying object"動作,
: 所以如果依此去解釋"傳reference type時就是傳reference alias"
: 那麼就會出現上面這種錯誤的推論了~
: 我的建議是,盡量使用JLS中所用的詞,因為Java與C++有些東西同名不同義
: 在討論時容易造成誤解,其實Java的行為是比較簡單,總之就是call by value
: 什麼都是傳副本,只是看你今天要傳的是"primitive value"的副本,
: 還是"reference value"的副本。
alias是很重要的一個觀念。
因為若不了解則在使用物件時可能隱藏了bug
詳細解說請參考thinking in java,前面介紹reference的章節,
與附錄介紹clone的章節
此外,
<%
: public void method(Object y) {
: y = null; //若此y是前面x的alias,
: //那麼在y上的動作等於在x上
: }
%>
java中唯一有operator overload的物件只有String
唯一合法改變物件內容的方使是呼叫其公用方法(或其他許可的情況)
我將原生變數與物件參考分開講是基於實際上的結果
原生變數的副本並不能互相影響, 是獨立的
而物件參考的副本, 就是別名。會不會互相影響視其是否為可變動物件而定。
若要其互相獨立需執行clone方法。
ps. 令y=null正好讓我回想起一個可呼應原旨的想法
依Practical Java建議, 希望GC快點收回不用的空間時
較好的方法是不再使用的物件為null :)
--
不怕名詞多而混淆, 只怕自己辭不達義而已。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 210.243.48.61
> -------------------------------------------------------------------------- <
作者: jackyhuang (雪.狼.湖) 看板: java
標題: Re: [問題] 問一個 記憶體 和 GC 的問題
時間: Wed Feb 1 00:12:02 2006
※ 引述《qrtt1 (thinking in java)》之銘言:
: ※ 引述《jackyhuang (雪.狼.湖)》之銘言:
: alias是很重要的一個觀念。
: 因為若不了解則在使用物件時可能隱藏了bug
: 詳細解說請參考thinking in java,前面介紹reference的章節,
: 與附錄介紹clone的章節
你和我對alias的對象指的不一樣
我說你寫"reference alias"會混淆的原因
是因為會讓人以為是"reference's alias"
而書上寫的是"alias a reference to an object"
: java中唯一有operator overload的物件只有String
: 唯一合法改變物件內容的方使是呼叫其公用方法(或其他許可的情況)
這不是我舉這個例子的原意
: 我將原生變數與物件參考分開講是基於實際上的結果
: 原生變數的副本並不能互相影響, 是獨立的
: 而物件參考的副本, 就是別名。會不會互相影響視其是否為可變動物件而定。
: 若要其互相獨立需執行clone方法。
複製的reference value彼此也是互相獨立的
只是他們指向同樣的一個object instance
所有的東西你在Java當然都講得通,但是如果把C++的用詞混進來(reference, alias...)
我覺得這樣的說法只會讓人更混亂,reference value亦是被call by value
複製一份過去的行為,有那麼難接受嗎? 我不敢說thinking in java寫得不清楚
但我認為JLS寫得很清楚,它是官方文件權威性不會比作者低
我個人猜thinking in java的作者是從他過去對C/C++的經驗,角度去解釋java
我認為這已經接近在用詞上的爭論,所以我也就不再回這篇文章
最後我以前輩TAHO的文章做為結尾,我認為TAHO前輩這篇文章已經足以終結這個討論串
--
TAHO前輩的文章
發信人: companion.bbs@bbs.nsysu.edu.tw (癡人), 看板: java
標 題: call by XXX 必也正名乎....
發信站: 中山計中美麗之島 (Tue Oct 30 12:38:01 2001)
轉信站:
nhctc_bbs!news.NHCTC!ctu-peer!news.nctu!news.cis.nctu!News.Math.NCTU!ne
Origin: bbs.nsysu.edu.tw
好吧.....
既然要討論 那就要先來正名一下
首先 得先釐清
何謂 call by value 又何謂 call by reference
當然在這之前 要先定義好 什麼是 value 什麼是 reference
因為最近在翻譯 JLS 所以我引用 JLS 裡面對這兩個詞的用法
( 這份文件應該可以代表 sun 的官方看法吧? )
據我的感覺
在 Java 中 有兩種 Type
也就是 primitive type 跟 reference type
這兩種 Type 限制了 variable 所能握有(hold) 的 value 種類
而所謂的 value 當然就是指 "值",也就是資料的直接內容
(指其位元碼,而非其代表的意義)
所謂的 primitive type 我喜歡翻譯為基本型別
這種型別的 value 被稱之為 primitive value
這種 value 所代表的就是一個數量 一個大小 並不是用來代表其他任何東西的
所謂的 reference type 一般我們翻譯成 "參考型別"
這種型別的 value 被稱為 reference value
而這個 reference value 並非是實際上應用的東西 不是一個數量
它只是個參考 是一個可以 指向物件 的參考
也就是可以根據 reference value 去找到物件
但是 reference value 並不等於是物件
( 其實 reference value 跟 reference 混用 並不會照成太大的困擾 )
也就是說 value 可分為兩種,分別為 primitive value 跟 reference value
而所謂的 variable(常常翻譯成變數) 則可以握有(hold) 這兩種東西
當 variable hold 的是 primitive value 時
我們稱這個 variable 是 primitive type 的變數
反之 當 variable hold 的是 reference value 時
我們稱這個 variable 是 reference type 的變數
( 注意,這句話是說 它是個 "參考型別的變數",而非 "它是個參考" )
所以 primitive value,reference value,variable,
primitive type,reference type,object
分別是代表不同的意義 不同的東西 不可混用
所以下面這兩個敘述
int i = 1;
String str = "test";
其中 i 跟 str 是 "變數"
"test" 是個字串的生成表示式,會生成 String 物件
1 是個整數的直譯字(literal)
int 跟 String 是 type
我們是看不到 value 的,他們是被 hold 在變數中的
另外
i 跟 str 雖然都是變數
但是 JVM 可以知道
i 是 primitive type 的變數, str 是 reference type 的變數
至於要分辨那屬於那種 type 的原因
是要知道當我們使用變數 hold 住的 value 時 (當然是一堆位元碼)
這些碼代表的到底是 primitive value 還是 reference value
比如說如果他的內容是 749452
那這個 749452 代表的是一個數量值,還是記憶體中的一個位置區塊
請注意:
嚴格來說
str 是個 variable 是一個 reference type 的 variable
str 不是一個 參考 而是握有參考值
str 也不是一個 物件 而是握有指向物件的參考值
平常我們在說 "str 物件" 只是為了方便起見 在討論這些東西時 要說清楚才行
於是
如果所謂的 call by value,是把 value 複製一份給別人
那麼 call by reference 就是把 reference 複製一份給別人
在這種前提下稱
"Java 在傳遞 reference type 引數時 是 call by reference"
是沒有問題的
Java 確實是把 variable 所 hold 的 reference value 複製一份
或者可以把 call by reference 改稱為 call by reference value 會更清楚
這種情況下甚至可以說
call by reference 是 call by value 的一種
而 "在傳遞 primitive type 的引數時,是 call by primitive (value)"
call by primitive 也是 call by value 的一種
如果是這樣,
那 Java 是 call by reference (value) 也是 call by value
因為 reference value 也是一種 value
這時候去爭論 Java 是 call by value 還是 call by reference 有甚麼意義呢?
如果把 variable reference object 混為一談 value 的意義又沒有規範清楚
把人家說的 call by reference 當成 call by object 的意思
然後把別的語言的用法套到 Java 上
那就亂成一團 也難怪會吵翻天了.......
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.121.212.1