1.變量及運(yùn)算符

1.變量及運(yùn)算符

基本概念

  • 所有東西都要存在內(nèi)存才能進(jìn)一步被使用(請(qǐng)不要抬杠??)
  • 一般地,這些東西要起名才方便使用
  • 更一般的,名字不能重名,否則將導(dǎo)致歧義
  • 進(jìn)一步的,有些名字不能起,因?yàn)榍叭艘呀?jīng)占用了
  • 內(nèi)存是寶貴的資源,從計(jì)算機(jī)誕生到內(nèi)存白菜價(jià)的今天依然適用
  • 所以放在內(nèi)存里的東西得提前確定好大小以便分配內(nèi)存空間,系統(tǒng)不會(huì)「看心情」多分配
  • Java 已有預(yù)定義的基本類型來指定一個(gè)東西占的內(nèi)存大小

由以上可知,要使用一個(gè)東西,起碼要考慮兩個(gè)方面:①類型②名字

變量類型

Java是靜態(tài)強(qiáng)類型的語言,這意味著,在Java的世界里,所有東西都得有確定的類型,并且一經(jīng)指定,類型再不可更改。比方說你有5個(gè)蘋果,我可以使用預(yù)定義類型int來指定存儲(chǔ)的這個(gè) 5 的類型或者說指定這個(gè) 5 占多大內(nèi)存;又或者描述圓周率 π,我可以使用預(yù)定義類型double來指定存儲(chǔ)的這個(gè) 3.14159... 的類型或者說指定其占多大內(nèi)存。

有些其他語言可能是動(dòng)態(tài)類型或者是弱類型,以下附圖(看看即可)

常見語言

更完整的類型系統(tǒng)對(duì)比表格參見(不看亦可):

https://en.wikipedia.org/wiki/Comparison_of_programming_languages_by_type_system

以下是Java預(yù)定義的8個(gè)基本類型

分類 名字及內(nèi)存占用
整數(shù) byte-1字節(jié);short-2字節(jié);int-4字節(jié);long-8字節(jié)
浮點(diǎn)數(shù) float-4字節(jié);double-8字節(jié)
字符 char-JVM 內(nèi)部占用2字節(jié)
布爾類型 boolean-不探討占內(nèi)存大小

最常用的是intdouble、charboolean。另外如果直接把 10、20 這樣的字面量常量寫在程序里,會(huì)認(rèn)為這是 int類型,如果直接寫 3.14 會(huì)認(rèn)為這是double。

另外上面提到了「JVM」,這是指「Java 虛擬機(jī)」,不展開講,簡(jiǎn)單地說 Java 程序無法直接「感知」到物理計(jì)算機(jī),因?yàn)槠鋵?shí)際運(yùn)行在 JVM 虛擬出的環(huán)境中??梢赃@么認(rèn)為 JVM 就是 Java 程序的運(yùn)行環(huán)境,Java 程序認(rèn)為 JVM 就是「真實(shí)」的計(jì)算機(jī)。打個(gè)比方,《黑客帝國(guó)》中人們生活在 Matrix 虛擬出的世界中,這里的 JVM 可以類比是 Matrix,Java 程序是生活在里面的人。后面再提到的「計(jì)算機(jī)」、「運(yùn)行環(huán)境」都是指 JVM,不再?gòu)?fù)述。

名字

如果直接使用 10、20、3.14 這樣的數(shù)不是不行,但是如果多個(gè)地方都要引用該數(shù)值,寫的就太麻煩了。我們可以起個(gè)名字來代指這個(gè)數(shù)值。如果可以多次更改其值就叫變量,如果賦值一次后再不可更改叫常量,都是字面意思,不解釋了?,F(xiàn)在先探討變量,常量到 Java OOP 提到final再說。

Java標(biāo)識(shí)符命名是有規(guī)則:

  • 名字必須由字母、數(shù)字、下劃線 _、美元符號(hào) $ 組成
  • 不能以數(shù)字開頭
  • 不能和已有變量名重名
  • 不能和特定詞即關(guān)鍵字(key word)重名

把握以上 4 點(diǎn)就不會(huì)錯(cuò)了。比如以下命名是合法的:abc、ABC123、a_123、_abc、$abc、蘋果,而這些是不合法的:2abc、abc#456、xyz abc。最后一個(gè)不合法是因?yàn)橹虚g有空格。

提一下,這里所稱的字母并不單單指英文字母,也包括其他國(guó)家語言文字的字符,比如上面的合法示例「蘋果」,這正是Java從誕生起就是原生支持多國(guó)語言文字特性的優(yōu)勢(shì)(??雖然采用 Unicode-16 有大坑,不再詳述)。

但是!推薦起名的做法是

  • 始終以英文字母開頭
  • 遵守小駝峰命名法

小駝峰命名法是指如果名字是由多個(gè)單詞組成的,那么第一個(gè)單詞首字母小寫,從第二個(gè)單詞起,每個(gè)單詞的首字母都大寫。比如這些:maxGrade、minSalary、writeObject。本教程將始終堅(jiān)持小駝峰命名法,后不再?gòu)?fù)述,直到類名采用大駝峰命名法時(shí)再提命名規(guī)范。

變量聲明和使用

上面提到了變量,Java中聲明一個(gè)變量是簡(jiǎn)單的,比如下面這樣:

int apple = 5;

這是聲明了一個(gè)int類型的變量,叫 apple,并立即初始化為 5,它占內(nèi)存 4 字節(jié)。所有變量的聲明語法都是一樣的,先是變量類型,再是變量名字。再看幾個(gè)例子:

double pi = 3.14159;
char letterA = 'a';
char letterB = '中';
boolean b1 = true;
boolean b2 = false;

其中字符類型的值必須用兩個(gè)「單引號(hào)」包裹住,布爾類型只有兩個(gè)合法值 true 和 false(??雖然 JVM 底層就把 boolean 當(dāng)成 int,不展開談)。留意到上述字符類型的值可以為漢字,這也是 Java原生支持多國(guó)語言文字的便利。

我們?cè)倏纯雌渌模覀兛梢詫?duì)變量做些簡(jiǎn)單運(yùn)算,比如

int apple = 5;
apple = apple + 3;

上述代碼的意思是把 apple 這個(gè)變量的原值 5 拿出來和 3 做加法,然后把結(jié)果再賦值給 apple,即是 8。要指出的是第 2 行代碼不要看成是數(shù)學(xué)里面的概念,不能改成如下形式

apple - apple = 3 ==》0 = 3

這也許是初學(xué)者一開始不理解的地方,0 怎么會(huì)等于 3 了。我要指出的是上述代碼不是數(shù)學(xué)里面的表達(dá)式,不能把變量在等號(hào)左右變來變?nèi)?。編程里面,等?hào)的意思是賦值,先計(jì)算右邊的結(jié)果,再賦值給左邊。

更多的運(yùn)算符

可以先看看最常見的「五則運(yùn)算」

int num = 1 + 2 - 3 * 5 / 5 % 6;

其中加減不必談,* 是乘法的意思,不能用 X 代替,/ 是除法的意思,不能用 ÷ 代替(你也敲不出這個(gè)符號(hào)??),% 是數(shù)學(xué)里取余(求模)的操作,比如 10÷3=3······1,則10%3的結(jié)果就是 1。求模在計(jì)算機(jī)科學(xué)里有重要的作用,這里不展開。按照先乘除后加減的順序(優(yōu)先級(jí),后面詳細(xì)介紹)計(jì)算,num 的結(jié)果是 0。

算術(shù)運(yùn)算符

顧名思義就是做計(jì)算的,一共有 5 個(gè)。

意義 符號(hào)
加法 +
減法 -
乘法 *
除法或整除 /
取余 %

除了/外,別的運(yùn)算符很簡(jiǎn)單,用法已經(jīng)在上面提到了。而/在不同計(jì)算里有不同的含義。

  • 如果左右操作數(shù)都是int,那就代表整除。結(jié)果是做數(shù)學(xué)除法后直接舍掉(不是四舍五入)小數(shù)部分,比如6/2的結(jié)果是 int 類型的 3,而10/3的結(jié)果也是 int 類型的 3。
  • 如果左右操作數(shù)有一個(gè)是浮點(diǎn)數(shù)類型,那就是普通的除法,是數(shù)學(xué)上的結(jié)果,有小數(shù)位,比如10.0/3 的結(jié)果就是 double 類型的 3.33 (具體精度后面再說)

關(guān)系運(yùn)算符

數(shù)學(xué)上有大于、等于、小于的比較運(yùn)算符,Java也提供了這些對(duì)應(yīng)的運(yùn)算符。

意義 符號(hào)
大于、大于等于 >、>=
是否相等 ==
小于、小于等于 <、<=
不等于 !=

注意,大于等于不能用數(shù)學(xué)上的符號(hào) ≥(你也敲不出這個(gè)符號(hào)??),小于等于、不等于同理。另外就是判斷兩個(gè)變量是否相等要用連續(xù)兩個(gè) =,而不是一個(gè) =,請(qǐng)一定要注意這一點(diǎn),這是初學(xué)者最容易犯的錯(cuò)誤之一。

關(guān)系運(yùn)算符運(yùn)算的結(jié)果是true或者false。

邏輯運(yùn)算符

數(shù)學(xué)上有「與」、「或」、「非」的概念,Java也提供了對(duì)應(yīng)運(yùn)算符。

意義 符號(hào)
邏輯與 &&
邏輯或 ||
邏輯非 !

邏輯運(yùn)算的規(guī)則不再繁述。

自增、自減運(yùn)算符

和 C語言一樣,Java也提供了這個(gè)快捷的操作。在程序中對(duì)變量遞增 1 或遞減 1 是很常見的運(yùn)算,此時(shí)可以這樣寫:

int i = 0;
i++; //現(xiàn)在 i 的值是 1
++i; //現(xiàn)在 i 的值是 2

而不用這樣寫 i = i + 1。上面看到了前綴形式和后綴形式,它們是有區(qū)別的。再看例子:

int m = 1,n = 1;
int j = m++; //j 的值是 1,m 變成 2
int k = ++n; //k 的值是 2,n 變成 2

該怎么理解上述代碼呢?其實(shí)前綴++會(huì)先把 n 做自增 1,變成 2,然后把 2 賦值給 k,所以 k 和 n 都是 2;而后綴++會(huì)先把 m 的原值賦值給 j,然后 m 再自增 1。如果對(duì)代碼做反編譯會(huì)看得更明白,但是不展開。自減是同理,不再舉例子。

一般來說前綴形式不會(huì)有歧義,先改變變量值再參與運(yùn)算,最讓人迷惑的是后綴。比如:

int a = 5, b = 6;
int c = a++ + b++; // 執(zhí)行完后 a 的值是 6,b 的值是 7,c 的值是 11

為什么變量 c 是 11?和上面的分析一樣,把 a、b的原值拿出來做加法,所以是11,然后 a、b的各自自增 1。但是!實(shí)際中不要在一個(gè)表達(dá)式不要寫出兩個(gè)及以上后綴,就像上面那樣,也不要混用前綴和后綴,比如:

int a = 5;
int c = ++a + a++; //有結(jié)果,但是這樣寫是不符合工程規(guī)范的,這是考驗(yàn)人的眼睛

還有變量后綴++然后賦值給自己的:

int a = 5;
a = a++; //有結(jié)果但不是想的那個(gè)結(jié)果,這就牽扯到別的問題了

實(shí)際中,要么使用i++單獨(dú)一行的形式,要么最多允許這樣a = b + c++,更復(fù)雜的形式就不該寫了。有前輩這樣說

代碼是給人看的,只是偶爾在機(jī)器上運(yùn)行

寫代碼是為了解決問題,不是為了炫技,寫正確、簡(jiǎn)潔的代碼不要寫有歧義的代碼。

復(fù)合賦值運(yùn)算符

有時(shí)候?yàn)榱撕?jiǎn)潔,把諸如a = a + 3這樣的形式寫成a += 3,+=是復(fù)合運(yùn)算符,在單獨(dú)寫一行不跟別的運(yùn)算符混合時(shí)和前者寫法等價(jià),實(shí)際中不要寫出a+=3+1這樣的寫法,只允許單獨(dú)用不可以和別的運(yùn)算符混合,原因和后綴++一樣,為了代碼一目了然?!肝鍎t運(yùn)算」都擁有復(fù)合形式。

運(yùn)算符 范例 結(jié)果
+= a += b a = a + b
-= a -= b a = a - b
*= a *= b a = a * b
/= a /= b a = a / b
%= a %= b a = a % b

類型轉(zhuǎn)換

前面說過,Java是很看重類型。事實(shí)上,一般地,不同類型的數(shù)據(jù)是不能做運(yùn)算的,比如:

long a = 3;
int b = a; // 代碼錯(cuò)誤

第 2 行 b 是int類型,a 是long類型,long占的空間更大,可存儲(chǔ)的數(shù)字更大,它是不能賦值給較小空間,可存儲(chǔ)數(shù)字較小的int變量的。但是第 1 行 3 是int類型,怎么就可以賦值給long的變量呢?因?yàn)?code>Java允許自動(dòng)類型轉(zhuǎn)換(也稱隱式類型轉(zhuǎn)換),簡(jiǎn)單說就是不同的類型的數(shù)據(jù)做運(yùn)算,運(yùn)算時(shí)以長(zhǎng)度最長(zhǎng)的類型為主,其他數(shù)值自動(dòng)提升至最長(zhǎng)的類型(如上述代碼第 1 行),但是反過來不行(如第 2 行)。如果確實(shí)類型要向下轉(zhuǎn)換,那得使用專門的語法——強(qiáng)制類型轉(zhuǎn)換(也稱顯式類型轉(zhuǎn)換),如下所示的圓括號(hào):

double a = 3.14;
int b = (int)a; //b 的值是 3,直接舍掉小數(shù)位

一般地,少用強(qiáng)制類型轉(zhuǎn)換,也不要濫用隱式類型轉(zhuǎn)換,最好始終堅(jiān)持同類型的數(shù)據(jù)做運(yùn)算。

運(yùn)算優(yōu)先級(jí)

運(yùn)算符優(yōu)先級(jí)有著嚴(yán)格的規(guī)定,一個(gè)表達(dá)式執(zhí)行順序是先按運(yùn)算符優(yōu)先級(jí),高的(數(shù)字越小越高)先執(zhí)行,同樣優(yōu)先級(jí)的,再按結(jié)合性的順序執(zhí)行。以下見表(看看即可):

優(yōu)先級(jí) 運(yùn)算符 簡(jiǎn)介 結(jié)合性
1 [ ]、.、( ) 方法調(diào)用,屬性獲取 從左向右
2 !、~、 ++、 -- 一元運(yùn)算符 從右向左
3 * 、/ 、% 乘、除、取模(余數(shù)) 從左向右
4 + 、 - 加減法 從左向右
5 <<、 >>、 >>> 左位移、右位移、無符號(hào)右移 從左向右
6 < 、<= 、>、 >=、 instanceof 小于、小于等于、大于、大于等于, 對(duì)象類型判斷是否屬于同類型 從左向右
7 == 、!= 2個(gè)值是否相等,2個(gè)值是否不等于。 下面有詳細(xì)的解釋 從左向右
8 & 按位與 從左向右
9 ^ 按位異或 從左向右
10 | 按位或 從左向右
11 && 短路與 從左向右
12 || 短路或 從左向右
13 ?: 條件運(yùn)算符 從右向左
14 =、 += 、-= 、*= 、/=、 %=、 &=、 |=、 ^=、 <、<= 、>、>= 、>>= 混合賦值運(yùn)算符 從右向左

事實(shí)上,不用全部記住這個(gè)表格,只需要記?、傧瘸顺蠹訙p;②自增自減比乘除還高;③括號(hào)優(yōu)先級(jí)更高,當(dāng)不清楚先運(yùn)算那個(gè)時(shí)就打括號(hào)以明確。

其他

  • 要知道浮點(diǎn)數(shù):double,float存儲(chǔ)可能不準(zhǔn)確,從而導(dǎo)致算術(shù)運(yùn)算結(jié)果也不準(zhǔn)確,一定不能用==來判斷兩個(gè)浮點(diǎn)數(shù)是否相同。這不是Java的錯(cuò),原因不展開,有興趣可以自行搜索。如果要精確的小數(shù)計(jì)算,可以使用BigDecimal類來解決,在后面的常見 Java 類使用中再予以介紹。
  • ASCII碼。應(yīng)該予以了解,但篇幅所限,這里不展開,網(wǎng)上有太多的文章。但要記住小寫字母 a,大寫字母 A 和字符 0 的 ASCII 碼,這是 IT 的常識(shí)。

還有什么沒有談到

以下內(nèi)容,有時(shí)間或?qū)W完了回頭再看看,正常學(xué)習(xí)時(shí)可以跳過。

  • 浮點(diǎn)數(shù)內(nèi)部存儲(chǔ)結(jié)構(gòu)
  • 浮點(diǎn)數(shù)為什么不準(zhǔn)確
  • 更多的邏輯運(yùn)算符
  • 位運(yùn)算及二進(jìn)制
  • 邏輯運(yùn)算規(guī)則
  • 邏輯運(yùn)算存在的「短路」現(xiàn)象
  • 反編譯看前綴++和后綴++
  • 數(shù)字字面量常量后綴 F 和 L
  • 不同整數(shù)類型能表示的最大值是規(guī)定的還是計(jì)算出來的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容