前言
做了這么久的Java開發(fā)坎炼,也非常喜歡這門語言,卻對它本身了解不多焚刚。而我又報名參加了2020年的藍橋杯Java組点弯,并且打算參加軟件杯和C4,為了能把這些比賽打好矿咕,在下學(xué)期的Java程序設(shè)計課里拿個高分(雖然能不能選上這門課還不一定)抢肛,也為了能對Java語言有一個更深入狼钮、系統(tǒng)的了解,不在以后的開發(fā)中對語言本身感到困惑捡絮,所以打算寫這個系列熬芜,從零開始重新學(xué)習(xí)Java基礎(chǔ)知識,并對第一次學(xué)習(xí)掌握得不好的部分重新記錄福稳。
參考資料
javac和java命令做了什么涎拉?
我們在安裝好JDK之后開始寫HelloWorld
程序時,都會用到javac
和java
兩條命令的圆。那么這兩條命令為我們做了些什么呢鼓拧?
javac
命令啟動了一個Java編譯器,它把后綴名為.java
的Java源碼文件編譯成了后綴名為.class
的字節(jié)碼文件越妈。java
命令則啟動了JRE
——Java運行時環(huán)境(Java Runtime Environment)和JVM
——Java虛擬機(Java Virtual Machine)季俩,裝載剛才編譯好的.class
文件并以解釋的方式執(zhí)行其中的字節(jié)碼。
(圖片來自Java300集)
所以梅掠,我們可以很清楚地看出為什么Java是半編譯半解釋的語言——因為源碼需要先編譯成字節(jié)碼酌住,字節(jié)碼在JVM中又是解釋執(zhí)行的。
這里如果展開了說還會涉及到Java語言阎抒、JVM的底層原理酪我,比如JVM是怎么加載這個類,怎么執(zhí)行其中的字節(jié)碼且叁,還有JIT即時編譯都哭、雙委派模型之類的,這里先不考慮這些細節(jié)谴古,在后面學(xué)習(xí)JVM基礎(chǔ)知識的部分再去詳細展開质涛。
JDK、JRE和JVM的關(guān)系
JRE并不等于JVM掰担。
除了JVM之外汇陆,JRE其實還包含一些庫函數(shù)和必須的文件,所以JRE其實是包含JVM的带饱。
JDK則在JRE的基礎(chǔ)上又增加了編譯器毡代、調(diào)試器等開發(fā)需要的東西。
JDK的目錄結(jié)構(gòu)
- bin:二進制文件勺疼,比如
java
教寂、javac
之類的,也就是我們用到的命令 - db:存放一些數(shù)據(jù)
- include:一些需要包含的頭文件
- jre:就是JRE
- lib:庫目錄执庐,存放了一些jar包
- src.zip:JDK源碼酪耕,不過為啥我macOS版的Java11沒這個呢?
標(biāo)識符
標(biāo)識符其實就是一個名字轨淌,用來給變量迂烁、包看尼、類等命名。
標(biāo)識符有一定的規(guī)則——
- 所有的標(biāo)識符都應(yīng)該以字母(A-Z 或者 a-z),美元符($)盟步、或者下劃線(_)開始
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)藏斩、下劃線(_)或數(shù)字的任何字符組合
-
class
等Java關(guān)鍵字不能用作標(biāo)識符
注意:Java使用的是Unicode標(biāo)準(zhǔn)字符集,所以可以用中文命名變量却盘。
數(shù)據(jù)類型
在Java中狰域,一共有8種基本類型(primitive type),其中有4種整型黄橘、2種浮點類型兆览、1種用于表示Unicode 編碼的字符單元的字符類型char和1種用于表示真值的boolean類型。
除此之外塞关,都是引用數(shù)據(jù)類型拓颓。它們占四個字節(jié),用來表示一個對象的地址(類似于C++的指針)描孟。
注意:Java有一個能夠表示任意精度的算術(shù)包,通常被稱為大數(shù)值(BigDecimal)砰左,但它并不是一種新的Java類型匿醒,而是一個Java對象。
變量的類型缠导、長度與范圍
整數(shù)類型
類型 | 長度 | 取值范圍 |
---|---|---|
int | 4字節(jié) | -2147483648~2147483647 |
short | 2字節(jié) | -32768~32767 |
long | 8字節(jié) | -9223372036854775808~9223372036854775807(-264~264-1) |
byte | 1字節(jié) | -128~127 |
注意:
長整型數(shù)值有一個后綴 L 或 l (如 4000000000L) 十六進制數(shù)值有一個前綴 0x 或 0X ( 如 0xCAFEL 八進制有一個前綴0廉羔,例如,010 對應(yīng)八進制中的 8僻造。 很顯然憋他, 八進制表示法比較容易混淆, 所以建議最好不要使用八進制常數(shù)髓削。并且竹挡,由于l容易和數(shù)字1、大寫的I混淆立膛,所以一般都使用大寫的L表示長整型數(shù)揪罕。
從 Java 7 開始, 加上前綴 0b 或 0B 就可以寫二進制數(shù)宝泵。 例如好啰, 0b1001就是 9。 另外儿奶, 同樣是 從Java7開始框往,還可以為數(shù)字字面量加下劃線,如用1_000_000表示一百萬闯捎,不會影響到編譯結(jié)果椰弊。
關(guān)于boolean的長度問題
Java規(guī)范中并沒有明確地指出boolean類型的長度许溅。但是,并不能說boolean的長度就不確定了:
在《Java虛擬機規(guī)范》一書中的描述:“雖然定義了boolean這種數(shù)據(jù)類型男应,但是只對它提供了非常有限的支持闹司。在Java虛擬機中沒有任何供boolean值專用的字節(jié)碼指令,Java語言表達式所操作的boolean值沐飘,在編譯之后都使用Java虛擬機中的int數(shù)據(jù)類型來代替游桩,而boolean數(shù)組將會被編碼成Java虛擬機的byte數(shù)組,每個元素boolean元素占8位”耐朴。也就是說JVM規(guī)范指出boolean當(dāng)做int處理借卧,也就是4字節(jié),boolean數(shù)組當(dāng)做byte數(shù)組處理筛峭,這樣我們可以得出boolean類型占了單獨使用是4個字節(jié)铐刘,在數(shù)組中是確定的1個字節(jié)。
from: https://blog.csdn.net/YuanMxy/article/details/74170745
雖說單獨使用的boolean
是跟int
一樣占用四個字節(jié)影晓,但是boolean
和int
不能相互轉(zhuǎn)換镰吵。
浮點類型
類型 | 長度 | 取值范圍 |
---|---|---|
float | 4字節(jié) | 大約 ± 3.402 823 47E+38F (有效位數(shù)為 6 ~ 7 位) |
double | 8字節(jié) | 大約 ± 1.797 693 134 862 315 70E+308 (有效位數(shù)為 15 位) |
浮點數(shù)不僅可以用小數(shù)點表示,也可以用科學(xué)計數(shù)法來表示挂签,例如314e2
疤祭、314E2
。
注意:float類型的數(shù)值有一個后綴F或f (例如饵婆,3.14F) 沒有后綴F的浮點數(shù)值(如3.14) 默 認(rèn)為 double 類型勺馆。當(dāng)然, 也可以在浮點數(shù)值后面添加后綴 D 或 d ( 例如侨核,3.14D)草穆。
注意2:Java中有三個特殊的浮點數(shù)值,它們可以用一些特殊的常量來表示:
- 正無窮大——
Double.POSITIVE_INFINITY
- 負無窮大——
Double.NEGATIVE_INFINIT
- NaN(不是一個數(shù)字)——
Double.NaN
可以用Double.isXxx
方法搓译,例如Double.isNaN
來檢測需要檢測的數(shù)是不是這三個常數(shù)悲柱。
注意3:與C/C++一樣,浮點數(shù)類型在計算時可能會產(chǎn)生誤差侥衬,因為浮點數(shù)并不是精確存儲的诗祸,可能產(chǎn)生舍入誤差,所以也最好不要比較兩個浮點數(shù)轴总。如果業(yè)務(wù)要求不能產(chǎn)生誤差或者必須要比較兩個浮點數(shù)直颅,需要使用BigInteger
(整數(shù))或者BigDecimal
(浮點數(shù))類。
注意4:Java提供了PI與E的近似值常量——Math.PI
怀樟、Math.E
功偿。
字符類型
char
類型可以表示的字符范圍為\u0000
到\uffff
。
注意:Unicode轉(zhuǎn)義序列會在解析代碼之前被處理,所以必須小心注釋中的\u
械荷,它們可能會引起一些意想不到的錯誤共耍。
自動類型轉(zhuǎn)換
下圖為Java不同數(shù)值類型之間的合法轉(zhuǎn)換(實線代表不會損失精度,虛線代表會損失精度吨瞎。圖片來自《Java核心技術(shù)》):
強制類型轉(zhuǎn)換
Java的強制類型轉(zhuǎn)換與C/C++基本相同痹兜,但是在面向?qū)ο蟛糠郑行┣闆r下不可以使用強制類型轉(zhuǎn)換颤诀,這一點在后面復(fù)習(xí)面向?qū)ο髸r再詳細總結(jié)字旭。
變量
變量的本質(zhì)
變量的本質(zhì)其實就是內(nèi)存中的一個可操作、固定長度的存儲空間(不過據(jù)說boolean的長度是不確定的)崖叫,在內(nèi)存中的地址是確定的遗淳,但是里面放置什么值是由程序運行決定的。我們可通過變量名來訪問對應(yīng)的存儲空間心傀,從而操縱這個存儲空間里存儲的值屈暗。
Java是一種強類型語言,聲明變量必須在變量名前先聲明其類型脂男,但是在Java11中养叛,能自動推斷出類型的可以不顯示指定類型而使用var
關(guān)鍵字指定,非常方便宰翅。
變量在使用前必須聲明, 只有在變量聲明以后一铅,才能為其分配相應(yīng)長度的存儲空間,所以在使用變量之前必須聲明堕油。
注意:使用沒有初始化局部的變量會報錯,但是聲明了變量不使用則不會報錯(這跟Go語言不一樣)肮之。
變量的分類
Java的變量與C++一樣掉缺,分為三種:
- 局部變量
- 靜態(tài)變量
- 成員變量/實例變量
成員變量的初值
成員變量從屬于對象,生命周期伴隨對象始終戈擒。
成員變量如果沒有初始化眶明,會有一個默認(rèn)值:
類型 | 默認(rèn)值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0 |
double | 0.0 |
char | '\u0000' |
boolean | false |
String等引用類型 | null |
靜態(tài)變量
靜態(tài)變量(使用static
聲明的變量)從屬于類,是生命周期最長的筐高,生命周期為從類的加載到類的卸載搜囱。
常量
與C/C++不同,常量使用final
關(guān)鍵字聲明柑土,一旦有值蜀肘,其值就不能發(fā)生變化。
final
關(guān)鍵字除了用于常量(不能修改的變量)之外稽屏,還有以下作用:
- 使用
final
修飾的類不能被繼承 - 使用
final
修飾的方法不能被重寫
這在后面復(fù)習(xí)面向?qū)ο蟮臅r候再詳細學(xué)習(xí)扮宠。
雖然Java不使用const
修飾常量,但是const
是Java的一個保留關(guān)鍵字狐榔,不能使用坛增。
運算符
Java中有以下運算符(圖片來自Java300集):
算術(shù)運算符
除了++
和--
以外都屬于二元運算符获雕,二元運算符運算時遵守以下規(guī)則:
- 如果兩個操作數(shù)有一個為Long, 則結(jié)果也為long。
- 沒有l(wèi)ong時收捣,結(jié)果為int届案。即使操作數(shù)全為short,byte罢艾,結(jié)果也是int楣颠。
- 如果兩個操作數(shù)有一個為double,則結(jié)果為double昆婿。
- 只有兩個操作數(shù)都是float球碉,則結(jié)果才為float。
- 取模操作其操作數(shù)可以為浮點數(shù)仓蛆,但是一般使用整數(shù)睁冬。結(jié)果是“余數(shù)”,“余數(shù)”符號和左邊操作數(shù)相同看疙,如:7%3=1豆拨,-7%3=-1,7%-3=1能庆。
++
與--
的運算規(guī)則與C/C++等語言相同施禾。
賦值運算與結(jié)合賦值運算
Java一共有以下幾種結(jié)合賦值運算符:
+=
-=
*=
\=
%=
用法與C/C++相同。
注意:如果整數(shù)除以0會拋出一個異常搁胆,而浮點數(shù)除以0則會得到無窮大或者是NaN弥搞。
關(guān)系運算符
Java的關(guān)系運算符一共有以下幾種:
==
!=
>
<
>=
<=
用法同樣與C/C++相同。
邏輯運算符
Java 沿用了 C++ 的做法渠旁,使用&&
表示邏輯“與”運算符攀例,使用||
表示邏輯“或”運算符。從 != 運算符可以想到顾腊,感嘆號!
就是邏輯非運算符粤铭。&&和||運算符是按照“短路”方式來求值的: 如果第一個操作數(shù)已經(jīng)能夠確定表達式的值,第二個操作數(shù)就不必計算了杂靶。
位運算符
Java中的位運算符與C/C++的基本相同梆惯,個人感覺這些東西在實際開發(fā)中很難用到,除非是在性能要求非常高的地方吗垮。
(圖片來自Java300集)
運算符的優(yōu)先級
Java運算符的優(yōu)先級也與C/C++基本相同垛吗。在實際使用中一般很少會遇到需要考慮優(yōu)先級的問題,一般都使用小括號來解決運算符的優(yōu)先級帶來的問題烁登,因為小括號的優(yōu)先級最高职烧。
(圖片來自Java300集)