lang包
java.lang包是Java語言的核心類庫(lang是language的縮寫),包括了運行Java程序必不可少的系統類,如基本數據類型、基本數學函數、字符串處理、線程、異常處理類等。每個Java程序運行時,系統都會自動地引入java.lang包,所以這個包的加載是缺省的。
思維導圖
Object
object是所有類的超類
Object類定義了一些有用的方法,由於是根類,這些方法在其他類中都存在,一般是進行重載或者重寫覆蓋,實現了給子類的具體功能。比如:
equals:返回值類型boolean,比較兩個對象是否相同
hashCode:返回值類型int,返回對象的哈希碼值
toString:返回值類型String,返回對象的字符串表示形式
在Obect類中有些方法使用native修改,native修飾示該方法的實現不是由java語言編寫的,native可以與其他修飾符一起使用,但是不能與abstract一起使用,abstract表示該方式是抽象的,不能有方法體,而native雖然沒有寫方法體,實質是存在方法體的。
注意:我們經常會比較兩個字符創內容是否相同,會使用equals()方法,或者使用工具類StringUtils,其實字符串String已經重寫了equals方法,所以可以直接使用比較兩個字符串內容是否一致,如代碼1,如果要比較一個自定義的實體類,那么就需要我們自己重寫equals(),比如代碼2,當然如果使用lombok
代碼1:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
代碼2:
public class TestEquals { private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public boolean equals(TestEquals testEquals){ return this == testEquals || (StringUtils.equals(this.getAddress(),testEquals.getAddress()) && StringUtils.equals(this.getName(),testEquals.getName())); } }
測試代碼:
public static void main(String[] args) { TestEquals testEquals = new TestEquals(); testEquals.setAddress("地球"); testEquals.setName("中國"); TestEquals testEquals1 = new TestEquals(); testEquals1.setName("中國"); testEquals1.setAddress("地球"); System.out.println(testEquals.equals(testEquals1)); } 結果: true
包裝類
Boolean,Character,Byte,Short,Integer,Long,Float,Double
知識點:裝箱和拆箱,類型轉換
自動裝箱:自動加基本數據類型轉成包裝類,如:Integer i = 1;
自動拆箱:自動將包裝類轉成基本數據類型,如:Integer i = 2;int n = i;
基本類型 包裝類 字節(byte) 位數(bit) 范圍
boolean Boolean N/A
byte Byte 1 字節 8 位 -128 ~ 127
char Character 2 字節 16 位 Unicode0 ~ Unicode(2^16)-1
short Short 2 字節 16 位 -2^15 ~ 2^15 - 1
int Integer 4 字節 32 位 -2^31 ~ 2^31 - 1
long Long 8 字節 64 位 -2^63 ~ 2^63 - 1
float Float 4 字節 32 位 IEEE754 ~ IEEE754
double Double 8 字節 64 位 IEEE754 ~ IEEE754
裝箱過程是通過調用包裝器的valueOf方法實現的,而拆箱過程是通過調用包裝器的 xxxValue方法實現的。(xxx代表對應的基本數據類型)。
比較常見的問題,如下:
public class Main { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); System.out.println(i3==i4); } }
結果:
true false
原因:其實查看Integer的ValueOf方法的源碼就知道了
//IntegerCache.high = 127 public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high){ return IntegerCache.cache[i + 128]; }else{ return new Integer(i); } }
如果i在[-128,127]集合內,返回指向的是IntegerCache.cache中已經存在的對象的引用,否則創建一個新的Integer對象,其實包裝類的ValueOf方法的實現方式不相同,比如:Double每次都會new一個Double對象,Integer只是一個例子,如果想了解其他包裝類的實現可以看看源碼。
比如:Double和Float每次都會創建一個新對象
public static Double valueOf(double d) { return new Double(d); } public static Float valueOf(float f) { return new Float(f); }
Short、Long和Integer類似
public static Short valueOf(short s) { final int offset = 128; int sAsInt = s; if (sAsInt >= -128 && sAsInt <= 127) { return ShortCache.cache[sAsInt + offset]; } return new Short(s); } public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
為什么要有包裝類?
我們知道Java是一個面相對象的編程語言,基本類型並不具有對象的性質,為了讓基本類型也具有對象的特征,就出現了包裝類型(如我們在使用集合類型Collection時就一定要使用包裝類型而非基本類型),它相當於將基本類型“包裝起來”,使得它具有了對象的性質,並且為其添加了屬性和方法,豐富了基本類型的操作。
包裝類和基本數據類型的區別
聲明方式不同:
基本類型不使用new關鍵字,而包裝類型需要使用new關鍵字來在堆中分配存儲空間;
存儲方式及位置不同:
基本類型是直接將變量值存儲在棧中,而包裝類型是將對象放在堆中,然后通過引用來使用;
初始值不同:
基本類型的初始值如int為0,boolean為false,而包裝類型的初始值為null;
使用方式不同:
基本類型直接賦值直接使用就好,而包裝類型在集合如Collection、Map時會使用到。
字符串
String ,StringBuilder, StringBuffer
在java.lang中還提供了處理字符串的String類,String類用於處理“不可變”的字符串,它們的值在創建后不能被更改;相對地,還提供了StringBuffer類和StringBuilder用於處理“可變”字符串。Stirng類,StringBuffer類和StringBuilder都被聲明為final類型,因此不能將其當做父類再被繼承使用了。
StringBuilder類和StringBuffer類是字符串緩沖區類,用於創建長度可變的字符串對象,這里的“長度可變”是指通過某些方法的調用可以改變字符串的長度和內容,比如通過在原字符串的基礎上追加新的字符串序列,或者在原字符串的某個位置上插入新的字符序列等構成新的字符串對象。常用的方法:append()和insert(),比如:
StringBuilder sb = new StringBuilder("abc"); System.out.println("1:"+sb); sb.append("d"); System.out.println("2:"+sb); sb.insert(1,"f"); System.out.println("3:"+sb);
結果:
1:abc 2:abcd 3:afbcd
String,StringBuffer和StringBuilder的區別
1.首先說運行速度,或者說是執行速度,在這方面運行速度快慢為:StringBuilder > StringBuffer > String
原因:String為字符串常量,而StringBuilder和StringBuffer均為字符串變量,即String對象一旦創建之后該對象是不可更改的,但后兩者的對象是變量,是可以更改的
Java中對String對象進行的操作實際上是一個不斷創建新的對象並且將舊的對象回收的一個過程,所以執行速度很慢。
而StringBuilder和StringBuffer的對象是變量,對變量進行操作就是直接對該對象進行更改,而不進行創建和回收的操作,所以速度要比String快很多
2.線程安全
在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的
如果一個StringBuffer對象在字符串緩沖區被多個線程使用時,StringBuffer中很多方法可以帶有synchronized關鍵字,所以可以保證線程是安全的,但StringBuilder的方法則沒有該關鍵字,所以不能保證線程安全,有可能會出現一些錯誤的操作。所以如果要進行的操作是多線程的,那么就要使用StringBuffer,但是在單線程的情況下,還是建議使用速度比較快的StringBuilder。
String直接賦值與new String()的區別
舉例說明:
String s1 = "abc"; String s2 = new String("abc"); String s3 = new String("ccc"); String s4 = new String("ccc"); System.out.println(s1 == s2); System.out.println(s3 == s4);
結果:
false false
首先s1是直接賦值,那么首先會去字符串常量池中查找是否存在abc,如果存在則直接將其內存地址賦值給s1,若不存在就會在字符串的常量池中創建,其次s2首先會在堆中創建字符串對象,並將引用地址賦值給s2,查看常量池中是否存在abc對象,如果存在就不再創建,若不存在則在常量池中創建
System
System類代表系統,系統級的很多屬性和控制方法都放置在該類的內部。由於該類的構造方法是private的,所以無法創建該類的對象,也就是無法實例化該類。其內部的成員變量和成員方法都是static的,所以也可以很方便的進行調用。
成員變量:in、out、err,分別代表標准輸入流(鍵盤輸入),標准輸出流(顯示器)和標准錯誤輸出流(顯示器)。
常用方法:
返回值 方法 功能
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 將指定源數組中的數組從指定位置復制到目標數組的指定位置。
static void currentTimeMillis() 返回當前時間(以毫秒為單位)。
static Properties getProperties() 獲取指定鍵指示的系統屬性。
static void gc() 運行垃圾回收器。
注意:在項目中不能使用system.out.println(),首先System.out.println只是將信息輸出到控制台,使用logger日志是可以輸出到指定的文件中,方便后續查看,還有更嚴重的問題就是將信息直接輸出到控制台會導致內存占用增大,甚至溢出,項目崩潰等問題。
Math
math類中包含執行基本數學運算的方法,比如:絕對值-abs()、較大值-max()、較小值-min{}、四舍五入-round()
https://www.cnblogs.com/cxscode/p/12869139.html
Throwable
Throwable
Throwable是 Java 語言中所有錯誤或異常的超類。
Throwable包含兩個子類: Error 和 Exception。它們通常用於指示發生了異常情況。
Throwable包含了其線程創建時線程執行堆棧的快照,它提供了printStackTrace()等接口用於獲取堆棧跟蹤數據等信息。
Exception
Exception及其子類是 Throwable 的一種形式,它指出了合理的應用程序想要捕獲的條件。
RuntimeException
RuntimeException是那些可能在 Java 虛擬機正常運行期間拋出的異常的超類。
編譯器不會檢查RuntimeException異常。例如,除數為零時,拋出ArithmeticException異常。RuntimeException是ArithmeticException的超類。當代碼發生除數為零的情況時,倘若既"沒有通過throws聲明拋出ArithmeticException異常",也"沒有通過try…catch…處理該異常",也能通過編譯。這就是我們所說的"編譯器不會檢查RuntimeException異常"!
如果代碼會產生RuntimeException異常,則需要通過修改代碼進行避免。例如,若會發生除數為零的情況,則需要通過代碼避免該情況的發生!
Error
和Exception一樣,Error也是Throwable的子類。它用於指示合理的應用程序不應該試圖捕獲的嚴重問題,大多數這樣的錯誤都是異常條件。
和RuntimeException一樣,編譯器也不會檢查Error
異常分類
Java將可拋出(Throwable)的結構分為三種類型:被檢查的異常(Checked Exception),運行時異常(RuntimeException)和錯誤(Error)。
運行時異常
定義: RuntimeException及其子類都被稱為運行時異常。
特點: Java編譯器不會檢查它。也就是說,當程序中可能出現這類異常時,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過。例如,除數為零時產生的ArithmeticException異常,數組越界時產生的IndexOutOfBoundsException異常,fail-fail機制產生的ConcurrentModificationException異常等,都屬於運行時異常。
雖然Java編譯器不會檢查運行時異常,但是我們也可以通過throws進行聲明拋出,也可以通過try-catch對它進行捕獲處理。
如果產生運行時異常,則需要通過修改代碼來進行避免。例如,若會發生除數為零的情況,則需要通過代碼避免該情況的發生!
被檢查的異常
定義: Exception類本身,以及Exception的子類中除了"運行時異常"之外的其它子類都屬於被檢查異常。
特點: Java編譯器會檢查它。此類異常,要么通過throws進行聲明拋出,要么通過try-catch進行捕獲處理,否則不能通過編譯。例如,CloneNotSupportedException就屬於被檢查異常。當通過clone()接口去克隆一個對象,而該對象對應的類沒有實現Cloneable接口,就會拋出CloneNotSupportedException異常。
被檢查異常通常都是可以恢復的。
錯誤
定義: Error類及其子類。
特點: 和運行時異常一樣,編譯器也不會對錯誤進行檢查。
當資源不足、約束失敗、或是其它程序無法繼續運行的條件發生時,就產生錯誤。程序本身無法修復這些錯誤的。例如,VirtualMachineError就屬於錯誤。
我們最常見的異常就是運行時異常(非檢查異常)
異常 描述
ArithmeticException 當出現異常的運算條件時,拋出此異常。例如,一個整數"除以零"時,拋出此類的一個實例。
ArrayIndexOutOfBoundsException 用非法索引訪問數組時拋出的異常。如果索引為負或大於等於數組大小,則該索引為非法索引。
ArrayStoreException 試圖將錯誤類型的對象存儲到一個對象數組時拋出的異常。
ClassCastException 當試圖將對象強制轉換為不是實例的子類時,拋出該異常
IllegalArgumentException 拋出的異常表明向方法傳遞了一個不合法或不正確的參數。
IndexOutOfBoundsException 指示某排序索引(例如對數組、字符串或向量的排序)超出范圍時拋出。
NullPointerException 當應用程序試圖在需要對象的地方使用 null 時,拋出該異常
NumberFormatException 當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換為適當格式時,拋出該異常。
我們常見的檢查異常
異常 描述
ClassNotFoundException 應用程序試圖加載類時,找不到相應的類,拋出該異常。
NoSuchFieldException 請求的變量不存在
NoSuchMethodException 請求的方法不存在
IOException 表示發生某種類型的I / O異常。 此類是由失敗或中斷的I / O操作產生的一般異常類。
SQLException 提供有關數據庫訪問錯誤或其他錯誤的信息的異常。
FileNotFoundException 指示嘗試打開由指定路徑名表示的文件失敗。
EOFException 表示在輸入過程中意外地到達文件結束或流結束。
異常處理
異常的處理方式有兩個:
方法1:通過throws拋出異常,由調用者處理該異常,例如:
private static final Logger logger = LoggerFactory.getLogger(TestClass.class);
//調用者處理異常
public static void main(String[] args) { try { String file = getFile(); System.out.println(file); } catch (IOException e) { logger.error("讀取文件異常",e); } }
//此方法通過throws方法將異常拋出
private static String getFile() throws IOException { File file = new File("C:\\文件\\test.txt"); FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader); StringBuilder stringBuilder = new StringBuilder(); String readLine ; while ((readLine = bufferedReader.readLine()) != null){ stringBuilder.append(readLine); } return stringBuilder.toString(); }
方法2:通過try…catch…捕獲異常,並處理
private static final Logger logger = LoggerFactory.getLogger(TestClass.class); public static void main(String[] args) { String file = getFile(); System.out.println(file); } private static String getFile() { File file = new File("C:\\文件\\test.txt"); try (FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader); ) { StringBuilder stringBuilder = new StringBuilder(); String readLine ; while ((readLine = bufferedReader.readLine()) != null){ stringBuilder.append(readLine); } return stringBuilder.toString(); }catch (Exception e){ logger.error("讀取文件異常",e); } return null; }
注釋類型
Override
override表示方法聲明旨在覆蓋父類的方法
小知識:
重載和重寫