Java基礎(chǔ)語法冷知識

概述
本篇文章只羅列了我所知道的,基本不涉及類知識的一些不太容易被人知曉的冷知識。
不過其實這些知識大多對生產(chǎn)沒有太大用處。
但是說不定哪天這些東西會幫助自己避坑呢?
在編程之前為什么需要配置環(huán)境變量?
exe和路徑的愛恨情仇
環(huán)境變量path的作用
自己定義環(huán)境變量并引用
而為了方便今后jdk路徑變更以及Java EE的使用,我們又將jdk的路徑單獨設(shè)置一個環(huán)境變量JAVA_HOME,然后path中填寫JAVAHOME\bin就完事兒了。以后如果要變更路徑,去改JAVA_HOME就行啦。
基礎(chǔ)語法基本數(shù)據(jù)類型中的冷知識(基于64位系統(tǒng))
基本數(shù)據(jù)類型與內(nèi)存的糾纏
int?a = 1;
int?b = 1;上面這行代碼,a和b使用的是同一塊內(nèi)存空間。什么意思呢?看下圖:

像"1"這樣的基本數(shù)據(jù)類型的值,我們稱為直接量。int b = 1;時,會先查找棧中是否存在直接量"1",如果找到了,那么直接使用這個直接量。
整數(shù)變量的賦值
我們都知道byte a = 1000; short b = 1000000之類的賦值會報錯:不兼容的數(shù)據(jù)類型,從int到byte(short),因為byte和short太小了。
強(qiáng)轉(zhuǎn),不強(qiáng)轉(zhuǎn)?
1.0和1.1的愛恨情仇
boolean?a = 1.0F == 1.0;
boolean?b = 1.1F == 1.1;這句話莫得毛病,但是點小有問題:
基本數(shù)據(jù)類型的==比較,比的是數(shù)值;而引用類型比的是地址。
不然為什么1.0 == 1.0F是true呢?是吧,哈哈哈。
boolean類型有多大?
這個問題標(biāo)準(zhǔn)答案是:沒有答案。
對,就是這樣,因為JAVA官方?jīng)]有指明一個boolean占多大內(nèi)存。
但是大眾普遍認(rèn)為大小是1個字節(jié),也不能算錯吧。
但更合理的猜測,不應(yīng)該是一個bit么?
自動類型轉(zhuǎn)換的一個小知識
我們都知道,自動類型轉(zhuǎn)換遵從小轉(zhuǎn)大的原則。
但是你知道么,這個小轉(zhuǎn)大,并不是完全指內(nèi)存的大小。
比如最特殊的一個:long類型可以自動轉(zhuǎn)換為float類型。
又有小老弟懵逼了,其實原因很簡單。
long類型表示的范圍是$-2^{63}$至$2^{63}-1$。
而float的表示范圍大概是$\pm10^{38} \approx \pm2^{114}$。
明顯float能表示的數(shù)字更大,所以能夠自動轉(zhuǎn)換。
當(dāng)然,自動轉(zhuǎn)換之后,也不可避免地會產(chǎn)生嚴(yán)重的誤差。
強(qiáng)制類型轉(zhuǎn)換如何取舍地?
byte a = 128;的結(jié)果是多少呢?
這就要涉及到強(qiáng)轉(zhuǎn)的數(shù)值取舍了。
小學(xué)二年級的時候都學(xué)過,128轉(zhuǎn)換為二進(jìn)制為:0000 0000 1000 0000。
因為byte類型就1個字節(jié),所以強(qiáng)轉(zhuǎn)之后,肯定需要舍棄一半。
java在進(jìn)行強(qiáng)制轉(zhuǎn)換時,舍棄的是高位部分,所以a的值最終為:1000 0000。也就是-128。
變量初始值
以前一直以為基本數(shù)據(jù)類型始終會有一個初始值,后來試了試,結(jié)果試試就逝世。
直接上結(jié)論吧
類成員變量(包括靜態(tài)的),無論是基礎(chǔ)數(shù)據(jù)類型還是引用數(shù)據(jù)類型,在不初始化的情況下都有初始值。
基本數(shù)據(jù)類型除了char,其他的初始值都是0(或者0.0)。
char類型初始值是’’。而引用數(shù)據(jù)類型初始值統(tǒng)一為null。而方法中的局部變量,不論是基本數(shù)據(jù)類型,還是引用類型,只要不初始化,直接編譯就報錯。
也就是說,下面這段代碼,打印結(jié)果是0。
如果把te.wa換成age,則直接編譯報錯。
public?class?VarTest?{
??int?wa;
??public?static?void?main(String[] args) {
????int?age;
????VarTest te = new?VarTest();
????System.out.println(te.wa);
??}
}運算符中的冷知識除以一個0.0試試
小學(xué)二年級就學(xué)過,java中除以0會報arithmeticExcetption。
那大家知不知道java能否除以0.0呢?
答案是可以說可以,也可以說不可以~
例如:
5 / 0.0的結(jié)果是infinity;
0 / 0.0的結(jié)果是NaN。
顯然都不是一個正常的數(shù)字,所以我們肯定也不應(yīng)該去除以0.0的哈。
賦值運算本身也會返回一個值
什么意思呢?
其實很(沒)簡(有)單(用)。
舉個栗子:
int?a, b;
a = b = 3;這段代碼執(zhí)行完之后,a和b都被賦值為了3。
因為b = 3這個表達(dá)式的結(jié)果是3。
運算結(jié)果的類型
小伙伴們覺得下面這段代碼執(zhí)行完后,a等于多少?
byte?a = 10;
a?= a + 2;結(jié)果等于:報錯~哈哈哈,想不到吧。
其實這是JAVA編譯器自動進(jìn)行了優(yōu)化處理。
因為byte的運算(算術(shù)運算、移位運算等)的計算結(jié)果被編譯器自動轉(zhuǎn)換為了int。
而int賦值給byte很顯然是會報錯的。
所以當(dāng)我們真的想寫這樣一段邏輯的話,需要使用如下寫法:
byte?a = 10;
a = (byte)(a + 2);或者!
還可以如下:
byte?a = 10;
a?+= 2;這就很騷了,原來a += 2;等價的不是a = a + 2;,而是a = (byte)(a + 2);。
同理,不光是+、也不光是short會有這種優(yōu)化。
可以自行嘗試一下其他地方是否也有如此特性。
如何高效(裝逼)地運算i*4?
大家都知道java中的位運算效率是最高的。
因為計算機(jī)底層就是二進(jìn)制,如果直接對二進(jìn)制進(jìn)行操作,java不需要再費精力去將變量與二進(jìn)制進(jìn)行轉(zhuǎn)換。
所以要高效地運算,最好的方法就是采用位運算。
而移位運算符剛好就具備倍乘、倍除的特性。
byte類型的9,二進(jìn)制為0000 1001。
左移一位,變?yōu)?001 0010,值為18。
不用懷疑,就是二倍。
同理,右移一位0000 0100,值為4。
也不用懷疑,就是整數(shù)/2的結(jié)果。
所以的所以,如何高效運算i*4?
答案是i = i << 2;。
當(dāng)然,我勸大家可別在實際開發(fā)中這樣寫,壞處很明顯:容易被打…好吧,其實是可讀性太低。
并且如果除符號位的最高位是1,左移之后的結(jié)果就很迷了。
