摘要:,變量里存的是什么在規(guī)范中,對于有這么一句話一個可以是一個類的實(shí)例或者是一個數(shù)組一個數(shù)組其實(shí)是一個,不過這是另一個話題了。由于的設(shè)計(jì)是不可變的,在一個實(shí)例上的任何增刪操作都會產(chǎn)生一個新的實(shí)例,效果與重新為變量設(shè)定新的引用值是一樣的。
考慮下面這個例子:
Long l1 = 1L; Long l2 = 2L; Long l3 = 3L; long l4 = 3L; Long l5 = 1 + 2L; System.out.println(l3 == 3); System.out.println(l4 == 3); System.out.println(l3.equals(3)); System.out.println(l3.equals(l4)); System.out.println(l3.equals(l5));
輸出的結(jié)果是
true true false true true
相信這個例子很多初學(xué)者都犯過迷糊:l3、l4 不都是 3 嗎,怎么 l3.equals(3) 是 false 呢。
這里面有很多點(diǎn)可以講的,我們一個一個來看:
Long 和 long在 Java 里只有兩種類型: primitive types 原始類型 和 reference types 引用類型。
null 是一種特殊的類型
規(guī)范說明:4.1. The Kinds of Types and Values
原始類型里包括:boolean、byte、short、int、long、char、float、double;
引用類型有四種:class、interface、type、array (其中 type 我們平時遇到過的就是泛型 T,詳細(xì)內(nèi)容可以查閱規(guī)范 4.4. Type Variables)
所以這里,long 是原始類型,Long 是引用類型,這很重要,是接下來討論的基礎(chǔ)。
Boxing Conversion 和 Unboxing Conversion其實(shí)這個就是拆箱裝箱,這個知識點(diǎn)應(yīng)該不陌生吧,就是 Java 會自動幫你把原始數(shù)值類型和原始浮點(diǎn)類型轉(zhuǎn)換為對應(yīng)的引用類型,如 long 轉(zhuǎn)換為 Long。
舉個栗子:
public void func(Long l) { System.out.println(l); } func(1L);
這段代碼是可以跑起來的,但是如果調(diào)用時是這樣的 func(1),那么就會報(bào)錯,因?yàn)?1 是整數(shù)型,它即便自動裝箱也是 Integer 而不是 Long。
Objects,變量里存的是什么在規(guī)范中,對于 Obejct 有這么一句話:
An object is a class instance or an array.
一個 Object 可以是一個類的實(shí)例或者是一個數(shù)組 (一個數(shù)組其實(shí)是一個 Object,不過這是另一個話題了。)
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.
引用值(通常是引用)是指向這些對象的指針和一個特殊的null引用,它不引用任何對象。
有些學(xué)過 C++ 的或是有 引用 這個概念的其他語言的同學(xué),可能在這里要犯迷糊了:不是說 Java 里沒有引用嗎,怎么規(guī)范里又提到這個詞了。
注意,C 里面沒有引用只有指針,它跟 Java 一樣是值傳遞的。
其實(shí)可以這么不嚴(yán)謹(jǐn)?shù)卣J(rèn)為:C++ 里的 引用 是動詞,Java 里的 引用 是名詞。
C++ 里的引用是對一個變量定義一個別名:
int a = 2, int &ra = a; // a為目標(biāo)原名稱,ra為目標(biāo)引用名。給ra賦值:ra = 1; 等價于 a = 1;
C++ 引用
Java 里的引用就是一個值,一個指向 對象 的值。
public static void func(String s) { s = "bar"; } String s1 = "foo"; func(s1); System.out.println(s1); // "foo"
在這里,s1 的值并不是 foo,而是一個指向 其字段value值為 ["f", "o", "o"]的 String 實(shí)例 的引用。
比如說,再聲明一個 String s2 = "foo";,然后在 func(s1); 處下斷點(diǎn),可以看到:
可以看到,String{@xxx} 和 value:byte[]{@xxx} 都是一樣的,因?yàn)樗鼈兙褪峭粋€對象,s1 和 s2 這兩個變量的值是 指向了同一個對象(String{@674})的引用。
如果我們在 func(String s) 里打斷點(diǎn),會發(fā)現(xiàn)在 func(s1) 的情況下,s 和 s1 的 引用值 是一樣的。
因?yàn)?Java 是值傳遞,只不過在引用類型的情況下,傳遞的這個值,就是 引用值。
當(dāng) func 內(nèi)部對這個 s 進(jìn)行操作后,我們再來看看func內(nèi)部斷點(diǎn)的情況:
public static void func(String s) { s = "bar"; // 斷點(diǎn)處,此時 s 的引用值已經(jīng)變?yōu)?String{@674} // 即此時的 s 的引用值已經(jīng)不再是 s1 的引用值,自此它們已經(jīng)指向的是不同的對象了。 }
由于 String 的設(shè)計(jì)是不可變的,在一個 String 實(shí)例上的任何增刪操作都會產(chǎn)生一個新的 String 實(shí)例,效果與重新為變量設(shè)定新的引用值是一樣的。
我們再看看一個原始類型的斷點(diǎn)情況:
int i = 0;
對于原始類型的變量而言,它們的值就是本身。
==和 equals== 操作符在規(guī)范里其實(shí)分了三種情況:
15.21.1. Numerical Equality Operators == and !=
15.21.2. Boolean Equality Operators == and !=
15.21.3. Reference Equality Operators == and !=
equals 是 Object 的方法,但是任何類都可以覆寫這個方法來實(shí)現(xiàn)自定義的實(shí)例間判斷,比如 Long.equals 就改成了這個樣子:
/** * Compares this object to the specified object. The result is * {@code true} if and only if the argument is not * {@code null} and is a {@code Long} object that * contains the same {@code long} value as this object. * * @param obj the object to compare with. * @return {@code true} if the objects are the same; * {@code false} otherwise. */ public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; }
也就是說,只要待判定對象不是 Long 或其子類,那么就直接返回 false。
結(jié)合前邊講的 int 在方法調(diào)用時會被自動裝箱成 Integer(如果參數(shù)不顯式要求 int 類型),很顯然,l3.equals(3) 會直接因?yàn)?Integer 3 不是 Long 而返回 false。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68602.html
摘要:這里強(qiáng)調(diào)一下,之前講過一個操作符按位取反操作符,區(qū)別一下他倆,按位取反操作符是針對二進(jìn)制數(shù)每一位全部都取反,包括符號位。 目錄 傳統(tǒng)藝能?過渡區(qū)?正片開始?數(shù)據(jù)類...
摘要:如線程執(zhí)行后,線程執(zhí)行,相當(dāng)于線程向線程發(fā)送了消息。我們可以利用這種互斥性來進(jìn)行線程間通信。 你是否真正理解并會用volatile, synchronized, final進(jìn)行線程間通信呢,如果你不能回答下面的幾個問題,那就說明你并沒有真正的理解: 對volatile變量的操作一定具有原子性嗎? synchronized所謂的加鎖,鎖住的是什么? final定義的變量不變的到底是什么...
摘要:文章目錄一數(shù)據(jù)類型二整型在內(nèi)存中的存儲原碼反碼補(bǔ)碼大小端三例題練習(xí)一數(shù)據(jù)類型在語言中有整型浮點(diǎn)型構(gòu)造類型指針類型等。正數(shù)的原反補(bǔ)碼都相同對于整形來說數(shù)據(jù)在內(nèi)存中存放的都是補(bǔ)碼。 ...
摘要:入門的導(dǎo)語廢話最近兩年你要說函數(shù)式編程不火的話那是不可能的是人都知道函數(shù)式編程很火為什么函數(shù)式編程會火呢在于它的思想很強(qiáng)大很強(qiáng)勢尤其是前端的更是在上完全使用純函數(shù)函數(shù)式的好處漸漸被發(fā)掘出來筆者最近看了一些函數(shù)式方面的東東現(xiàn)在發(fā)出來給大家學(xué)習(xí) 0x00 入門的導(dǎo)語(廢話) 最近兩年你要說函數(shù)式編程不火的話, 那是不可能的, 是人都知道函數(shù)式編程很火.為什么函數(shù)式編程會火呢, 在于它的思想...
閱讀 2988·2023-04-26 02:25
閱讀 2264·2023-04-25 18:05
閱讀 654·2021-09-30 09:57
閱讀 2949·2021-09-27 14:10
閱讀 1660·2019-08-30 15:44
閱讀 1010·2019-08-29 15:28
閱讀 2534·2019-08-29 14:10
閱讀 2267·2019-08-29 13:30