<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 3868字,需瀏覽 8分鐘

           ·

          2020-11-01 01:59


          概述


          • 本篇文章只羅列了我所知道的,基本不涉及類知識的一些不太容易被人知曉的冷知識。

            不過其實這些知識大多對生產(chǎn)沒有太大用處。

            但是說不定哪天這些東西會幫助自己避坑呢?


          在編程之前為什么需要配置環(huán)境變量?


          exe和路徑的愛恨情仇


          Windows執(zhí)行可執(zhí)行文件時,只能識別當(dāng)前目錄下的exe文件,而javac和java這兩個可執(zhí)行文件,都在jdk\bin中。我們當(dāng)然不能把所有.java文件都扔到這個目錄里面去執(zhí)行,這時候就需要用到path環(huán)境變量。


          環(huán)境變量path的作用


          path環(huán)境變量讓W(xué)indows執(zhí)行exe之前,先去path變量中從上到下(win7是從前到后)遍歷,如果其中存在對應(yīng)的exe,則可以直接執(zhí)行。

          正因為如此,我們才需要把jdk\bin目錄加入到path環(huán)境變量中


          自己定義環(huán)境變量并引用


          而為了方便今后jdk路徑變更以及Java EE的使用,我們又將jdk的路徑單獨設(shè)置一個環(huán)境變量JAVA_HOME,然后path中填寫JAVAHOME\bin就完事兒了。以后如果要變更路徑,去改JAVA_HOME就行啦。


          PS:java11之后不需要配置classpath了。


          基礎(chǔ)語法基本數(shù)據(jù)類型中的冷知識(基于64位系統(tǒng))


          基本數(shù)據(jù)類型與內(nèi)存的糾纏


          或許大家知道基本數(shù)據(jù)類型存儲在棧區(qū)中,數(shù)組和引用數(shù)據(jù)類型存儲在堆區(qū)中。但是大家可能容易忽略一個小細(xì)節(jié)。


          int?a = 1;
          int?b = 1;


          上面這行代碼,a和b使用的是同一塊內(nèi)存空間。什么意思呢?看下圖:




          像"1"這樣的基本數(shù)據(jù)類型的值,我們稱為直接量。int b = 1;時,會先查找棧中是否存在直接量"1",如果找到了,那么直接使用這個直接量。


          所以真正存儲在棧區(qū)中的其實是直接量,相同的直接量,不會重復(fù)占用多個內(nèi)存空間,這就是上面代碼a和b使用同一地址的原因。而不同的值會被分配到不同的地址去,所以如果a=1、b=2,那么他們的地址又是不同的。

          不同類型的相同值,也是會被分配到不同地址,很好理解嘛,因為他們需要的內(nèi)存大小都不一樣嘛。比如1.0和1.0F,他們的在棧中的地址是不一樣的。

          盡管這個特性看起來很像是“引用”,但是我們需要避免這樣去稱呼他們。因為“引用”指的是利用棧區(qū)中的內(nèi)存地址,指向堆區(qū)中的數(shù)據(jù)。


          整數(shù)變量的賦值


          我們都知道byte a = 1000; short b = 1000000之類的賦值會報錯:不兼容的數(shù)據(jù)類型,從int到byte(short),因為byte和short太小了。


          但你們知道int a = 9999999998會報什么錯么?不兼容的數(shù)據(jù)類型?并不是,報錯的內(nèi)容是:整數(shù)太大。

          這是為什么呢?因為在不加任何符號的情況下,1000、1000000、9999999998這些數(shù)字都是分配了4個字節(jié)的內(nèi)存進(jìn)行存儲,并且類型為int。而某清華學(xué)子說過,我們小學(xué)二年級就學(xué)過int最大的表示范圍大概是25億,顯然9999999998大于了這個數(shù)字。

          所以我們才需要使用int a = 9999999998L來解決這個問題。

          說到這兒,就像順道說一下,浮點數(shù)(例如1.0)的默認(rèn)類型是double,不是float喲~所以float b = 1.0F才能正確給float賦值喲~~~~


          強(qiáng)轉(zhuǎn),不強(qiáng)轉(zhuǎn)?


          看了上面兩小節(jié)之后,細(xì)的朋,哦不,細(xì)心的朋友們就要問了:byte a = 1;為什么不報錯?float b = 1.0;為什么報錯?

          這個問題我也只知道一個很淺顯的答案:對于byte范圍內(nèi)的值,JVM會自動將int(例如1)處理為byte,所以前者不報錯。而JVM表示并不想把doule處理成float,即使這個值在float的表示范圍內(nèi)。

          底層原因的話,猜測一下?可能是因為float和double是科學(xué)技術(shù)法表示的,轉(zhuǎn)起會惡心到JVM?望有大佬能夠明確一下答案。


          1.0和1.1的愛恨情仇


          我畫你猜,a和b那個是true?那個是false?:


          boolean?a = 1.0F == 1.0;
          boolean?b = 1.1F == 1.1;


          答案是,a真b假。

          哦喲,搞啥子哦?為啥子喃?簡單說一說:因為float和double都是近似值,并且精度不同,所以同樣是1.1,他們真實的值都有誤差,并且誤差程度不同,自然值就不同啦~而1.0之所以相同,純粹是巧合,因為剛好float和double都能精確表示1.0。

          也就是說,99.9%的情況,float和double都是沒法相等的。不信的話,給你們個網(wǎng)址,自己試一試浮點數(shù)的誤差會有多大:https://www.h-schmidt.net/FloatConverter/IEEE754.html==?

          某清華學(xué)子說,我們小學(xué)2年級都學(xué)過:==比較的是地址,equals通常比較的是具體的內(nèi)容(具體得看重寫的方法是怎么寫的)。

          這句話莫得毛病,但是點小有問題:


          基本數(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é)果就很迷了。



          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产免费色色情片 | 久久r这里只有精品 | 亚洲一区二区三区无码 | 在线观看亚洲免费视频 | 可以直接看的av 免费性爱视频网站 |