選單

Java 中常見的幾個陷阱,你沒有遇到幾個?

概述

Java 中常見的幾個陷阱,你沒有遇到幾個?

java 中有很多,新手經常遇到的陷阱,本文主要包含

自動裝箱與拆箱

不可變的String

記憶體洩漏

自增型別使用

使用 “==”進行物件比較

double 型別計算

不可變的String

Java String類是不可變的(不可修改)。這是因為String物件被快取在String池中。字串引用的物件可以更改,但字串物件本身不能更改。

Java 中常見的幾個陷阱,你沒有遇到幾個?

字串是不可變的。

一旦建立了字串,以後將無法更改該字串物件。

Java使用按值傳遞

,而不是按引用傳遞。當您在方法中為分配新值時,它只會修改本地,而不是呼叫程式碼中的原始s

Java 中常見的幾個陷阱,你沒有遇到幾個?

自動裝箱與拆箱

裝箱就是自動將基本資料型別轉換為包裝器型別;

拆箱就是自動將包裝器型別轉換為基本資料型別。

裝箱拆箱的型別有哪些?

Java 中常見的幾個陷阱,你沒有遇到幾個?

透過上圖,可以看出,java 基本型別可以進行拆裝箱。

那拆裝箱會出現什麼問題呢?

Java 中常見的幾個陷阱,你沒有遇到幾個?

Java 中常見的幾個陷阱,你沒有遇到幾個?

透過例項,上面兩個程式,

計算耗時相差近10倍

,在大量存在裝箱行為時,會導致程式效能低下。

當封裝型別進行==、+、-、*、/計算時,會自動拆箱,對基礎資料型別進行運算。所以在進行計算時,使用基本資料型別。

記憶體洩漏

Java的核心優勢之一是 Java垃圾收集器,它可以管理堆上的物件記憶體。每當物件不可訪問時,它將自動釋放。

但是,對於新手和有經驗的程式設計師而言,常見的錯誤是透過允許不再使用的物件可訪問來防止釋放記憶體。這可能對專案造成很大的不利影響,因為記憶體洩漏會阻塞資源並降低應用程式效能。它甚至可能導致java。lang。OutOfMemoryError。

常見的情況是:

靜態欄位宣告。靜態欄位,並在不再需要其資料後忘記將其設定為null

未正常關閉流。 Java虛擬機器為每個開啟的連線分配記憶體。忘記關閉連線會消耗記憶體。這樣的連線可以是:輸入流,資料庫連線,會話等。

finalize() 方法。當我們覆蓋的finalize()方法,finalize()只會在物件記憶體回收前被呼叫一次,具有不確定行,只保證方法會呼叫,但不保證方法裡的任務會被執行完。所以儘量避免使用。在Java 9 中,已經宣告為過期函式,

自增型別使用

Java中運算子的計算順序是在同等級下從左到右計算,看下自增情況

Java 中常見的幾個陷阱,你沒有遇到幾個?

第一種情況的執行上下文如下:

1。儲存運算元的先前值。

2。增加值。

3。返回上一個值

第二種情況的執行上下文如下:

1。增加值。

2。儲存運算元的值(遞增)

3。返回值

使用 “==”進行物件比較

許多新手程式設計師嘗試使用“ ==”運算子比較物件,並且當代碼的行為不符合預期時,就會感到困惑。需要注意的是,關係運算符“ ==”正在進行引用比較,它檢查兩個物件是否都指向記憶體中的相同位置。使用 。equals()方法將消除此問題,因為它會比較物件內部的值。

Java 中常見的幾個陷阱,你沒有遇到幾個?

儘管有時“ ==”運算子會給出預期的答案:

Java 中常見的幾個陷阱,你沒有遇到幾個?

這是什麼原因呢?同樣是字串,建立的方式不同,差距咋這麼大呢

Java語言規範的字串文字中:同一包中不同類內的文字字串表示對同一String 物件的引用

如果還不清楚那看下兩種字串建立過程

第一種new的方式

new一個字串時,做了兩件事。首先在堆中生成了該字串物件,然後去看常量池中有沒有該字串,如果有就不管了,沒有就往常量池中新增一個

Java 中常見的幾個陷阱,你沒有遇到幾個?

第二種,直接賦值

這樣建立字串,首先會去常量池裡找有沒有這個字串,有就直接指向常量池的該字串,沒有就先往常量池中新增一個,再指向它。

Java 中常見的幾個陷阱,你沒有遇到幾個?

上面就是兩種方式的對比情況了。

Java 中常見的幾個陷阱,你沒有遇到幾個?

兩個Integer 對比

Java 中常見的幾個陷阱,你沒有遇到幾個?

那為什麼100的時候就是相等200就不行了呢這是由於Integer 使用了快取。

Java 中常見的幾個陷阱,你沒有遇到幾個?

其static塊中就一次性生成了-128到127直接的Integer型別變數儲存在cache[]中,對於-128到127之間的int型別,返回的都是同一個Integer型別物件。

整個工作過程就是:Integer。class在裝載(Java虛擬機器啟動)時,其內部型別IntegerCache的static塊即開始執行,例項化並暫存數值在-128到127之間的Integer型別物件。

當自動裝箱int型值在-128到127之間時,即直接返回IntegerCache中暫存的Integer型別物件。

為什麼Java這麼設計?應該是出於效率考慮,因為自動裝箱經常遇到,尤其是小數值的自動裝箱;而如果每次自動裝箱都觸發new,在堆中分配記憶體,就太耗時了;

其它幾種基本型別包裝類,也進行了快取

Java 中常見的幾個陷阱,你沒有遇到幾個?

Double 型別計算

Java 中常見的幾個陷阱,你沒有遇到幾個?

Java中的double和float在內部表示為二進位制分數,因此在表示十進位制分數時可能不夠精確(IEEE標準754)。十進位制數計算需要精度,需要使用java。math。BigDecimal

總結

Java 中還有很多小陷阱,如果你有可以寫出來吆。

String 為什麼會設計成不可改變的呢?