日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java的标量和聚合量_第5节:Java基础 - 必知必会(下)

發布時間:2025/4/5 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的标量和聚合量_第5节:Java基础 - 必知必会(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第5節:Java基礎 - 必知必會(下)

本小節是Java基礎篇章的第三小節,主要講述Java中的Exception與Error,JIT編譯器以及值傳遞與引用傳遞的知識點。

一、Java中的Exception和Error有什么區別

Exception和Error的主要區別可以概括如下:

Exception是程序正常運行中預料到可能出現的錯誤,并且應該被捕獲并進行相應處理,是一種異?,F象。

Error是正常情況下不可能發生的錯誤,Error會導致JVM處于已追蹤不可恢復的狀態,不需要捕獲處理,比如說OutOfMemoryError

解析:

Exception又分為了運行時異常和編譯異常。

編譯異常(受檢異常)表示當前調用的方法體內部拋出了一個異常,所以編譯器檢測到這段代碼在運行時可能會出現異常,所以我們必須對異常進行相應處理,可以捕獲異常或者拋給上層調用方。

運行時異常(非受檢異常)表示在運行時出現的異常,常見的運行異常包括:空指針異常,數組越界異常,數字轉換異常以及算數異常等。

前面說到了異常Exception應該被捕獲,我們可以使用try-catch-finally來處理異常,并且使得程序恢復正常。

那么我們捕獲異常應該遵循哪些基本原則呢?

盡可能捕獲比較詳細的異常,而不是使用Exception一起捕獲。

當本模塊不知道捕獲之后該怎么處理異常時,可以將其拋給上層模塊。上層模塊擁有更多的業務邏輯,可以進行更好的處理。

捕獲異常后至少應該有日志記錄,方便之后的排查。

不要使用一個很大的try-catch包住整段代碼,不利于問題的排查。

NoClassDefFoundError 和 ClassNotFoundException 有什么區別?

從名字中,我們可以看出前者是一個錯誤,后者是一個異常。我們先來看下JDK中對ClassNotFoundException異常的闡述:

大概意思就是在說,當我們使用例如Class.forName方法來動態的加載該類的時候,傳入了一個類名,但是其并沒有在類路徑中被找到的時候,就會報ClassNotFoundException異常。出現這種情況,一般都是類名字傳入有誤導致的。

我們再來看下JDK中對該錯誤NoClassDefFoundError的闡述:

大概意思是這樣的,如果JVM或者ClassLoader實例嘗試加載(可以通過正常的方法調用,也可能是使用new來創建新的對象)類的時候卻找不到類的定義。但是要查找的類在編譯的時候是存在的,運行的時候卻找不到了。這個時候就會導致NoClassDefFoundError。出現這種情況,一般是由于打包的時候漏掉了部分類或者Jar包被篡改已經損壞。

二、JIT編譯器

前面我們談到了Java是一種先編譯,后解釋執行的語言。那么我們就來說下何為JIT編譯器吧。

JIT編譯器全名叫Just In Time Compile也就是即時編譯器,把經常運行的代碼作為"熱點代碼"編譯成與本地平臺相關的機器碼,并進行各種層次的優化。JIT編譯除了具有緩存的功能外,還會對代碼做各種優化,包括逃逸分析、鎖消除、 鎖膨脹、方法內聯、空值檢查消除、類型檢測消除以及公共子表達式消除等。

解釋:

JIT編譯器屬于Java基礎中的比較有深度的題目了,回答出來算是一個亮點了。既然說到了JIT編譯器,我們來看下JIT對代碼優化使用到的逃逸分析技術吧。

逃逸分析:

逃逸分析的基本行為就是分析對象動態作用域,當一個對象在方法中被定義后,它可能被外部方法所引用,例如作為調用參數傳遞到其他地方中,稱為方法逃逸。JIT編譯器的優化包括如下:

同布省略:也就是鎖消除,當JIT編譯器判斷不會產生并發問題,那么會將同步synchronized去掉

標量替換

我們先來解釋下標量和聚合量的基本概念。

標量(Scalar)是指一個無法再分解成更小的數據的數據。Java中的原始數據類型就是標量。

聚合量(Aggregate)是還可以分解的數據。Java中的對象就是聚合量,因為他可以分解成其他聚合量和標量。

在JIT階段,如果經過逃逸分析,發現一個對象不會被外界訪問的話,那么經過JIT優化,就會把這個對象拆解成若干個其中包含的若干個成員變量來代替。這個過程就是標量替換。標量替換的好處就是對象可以不在堆內存進行分配,為棧上分配提供了良好的基礎。

那么逃逸分析技術存在哪些缺點呢?

技術不是特別成熟,分析的過程也很耗時,如果沒有一個對象是不逃逸的,那么就得不償失了。

三、Java中的值傳遞和引用傳遞

值傳遞和引用傳遞的解釋可以概括如下。

值傳遞,意味著傳遞了對象的一個副本,即使副本被改變,也不會影響源對象。

引用傳遞,意味著傳遞的并不是實際的對象,而是對象的引用。因此,外部對引用對象的改變會反映到所有的對象上。

我們先看一個值傳遞的例子:

public class Test {

public static void main(String[] args) {

int x=0;

change(x);

System.out.println(x);

}

static void change(int i){

i=7;

}

}

毫無疑問,上邊的代碼會輸出0。因為如果參數是基本數據類型,那么是屬于值傳遞的范疇,傳遞的其實是源對象的一個copy副本,不會影響源對象的值。

我們再來分析一個引用傳遞的例子:

public class Test {

public static void main(String[] args) {

StringBuffer x = new StringBuffer("Hello");

change(x);

System.out.println(x);

}

static void change(StringBuffer i) {

i.append(" world!");

}

}

通過運行程序,輸出為Hello world!接下來我們通過圖片來分析下程序執行過程種的內存變化吧。

由圖中我們可以看出x和i指向了同樣的內存地址,那么i.append操作將直接修改了內存地址里邊的值,所以當方法結束,局部變量i消失,先前變量x所指向的內存值已經發生了變化,所以輸出為Hello world!

接著,我們修改下change方法,代碼如下所示:

public class Test {

public static void main(String[] args) {

StringBuffer x = new StringBuffer("Hello");

change2(x);

System.out.println(x);

}

static void change2(StringBuffer i) {

i = new StringBuffer("hi");

i.append(" world!");

}

}

先給出答案,上邊Demo的輸出為Hello,我們依然來畫圖分析內存變化。

由圖中我們可以看出來,在函數change2中將引用變量i重新指向了堆內存中另一塊區域,下邊都是對另一塊區域進行修改,所以輸出是Hello。

最后,我們繼續升級該題目代碼如下:

public class Test {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer("Hello ");

System.out.println("Before change, sb = " + sb);

changeData(sb);

System.out.println("After change, sb = " + sb);

}

public static void changeData(StringBuffer strBuf) {

StringBuffer sb2 = new StringBuffer("Hi,I am ");

strBuf = sb2;

sb2.append("World!");

}

}

輸出為:

Before change, sb = Hello

After change, sb = Hello

總結

以上是生活随笔為你收集整理的java的标量和聚合量_第5节:Java基础 - 必知必会(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。