1. 程式人生 > 實用技巧 >Java總結2

Java總結2

物件的記憶體示意圖

2、二維陣列中 實質是一維陣列,一維陣列中存的是另外陣列的地址

強制轉換的例子

char c = '1';
int i = c - 48;
char c1 = (char)(i +48);
System.out.println(c);
System.out.println(i);
System.out.println(c1);
//1
//1
//1

許可權修飾符

修飾詞本類同一個包的類繼承類其他類
private × × ×
無(預設) × ×
protected ×
public

protected 修飾的方法 在同一個包中呼叫 另一個包中繼承本包的子類 import 子包就好

如果在子包中其他類中使用本包的方法需要在子包中重寫方法才能使用

程式碼塊

有區域性程式碼塊,構造程式碼塊,靜態程式碼塊

區域性程式碼塊就是在方法中用{}括住的程式碼塊;可以改變變數的生命週期,提前釋放,提高效率

構造程式碼塊和靜態程式碼塊在繼承中的執行順序

開始執行

父類靜態程式碼塊

子類的靜態程式碼塊

父類的構造程式碼塊

父類的構造方法

子類的構造程式碼塊

子類的構造方法

結束

且靜態程式碼塊只會載入一次 如下:定義兩個類Person基類和Student子類

 static {
System.out.println("我是靜態人");
}
{
System.out.println("我是人");
}
private String name;
private int age;

public Person(){
System.out.println("我是構造人");
}

public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("我是構造人");
}
Student s = new Student();
System.out.println("----");
Student student = new Student("haha",23);
//我是靜態人
//我是靜態學生
//我是人
//我是構造人
//我是學生
//我是構造學生
//----
//我是人
//我是構造人
//我是學生
//我是構造學生

final

final修飾變數:表示常量,變數只能賦值一次

修飾類:不能被繼承

修飾方法:不能被覆蓋

修飾物件的時候:內容是可以變的,就是地址不能變。

匿名內部類

1、不能具有static成員域和成員函式和類。

2、不能具有static final 修飾的引用型別。

3、不能有自定義的建構函式。(好像預設有)

4、不能具有靜態程式碼塊。

5、匿名內部類不能有類修飾符

1、內部類可以直接呼叫外部類的方法包括private修飾的方法,但是外部類不能直接呼叫內部類方法

2、方法中的區域性變數,方法結束後這個變數就要釋放掉,final保證這個變數始終指向一個物件。   首先,內部類和外部類其實是處於同一個級別,內部類不會因為定義在方法中就會隨著方法的執行完畢而跟隨者被銷燬。問題就來了,如果外部類的方法中的變數不定義final,那麼當外部類方法執行完畢的時候,這個區域性變數肯定也就被GC了,然而內部類的某個方法還沒有執行完,這個時候他所引用的外部變數已經找不到了。如果定義為final,java會將這個變數複製一份作為成員變數內置於內部類中,這樣的話,由於final所修飾的值始終無法改變,所以這個變數所指向的記憶體區域就不會變。

注意,若使用JDK1.8,方法中內部類的方法是可以直接訪問外部類的方法的區域性變數,並且不需要宣告為final型別

BigInteger和BigDecimal

java中long型為最大整數型別,對於超過long型的資料如何去表示呢.在Java的世界中,超過long型的整數已經不能被稱為整數了,它們被封裝成BigInteger物件.在BigInteger類中,實現四則運算都是方法來實現,並不是採用運算子.

float和double都是近似計算的 當商業計算時應該用BigDecimal

這兩個類在計算是都是呼叫方法的比如add()

Date

    Date d = new Date();
System.out.println(d);
Date date = new Date(1000*60*60);
System.out.println(date);
long time = d.getTime();
System.out.println(time /1000/60/60/24/365);
d.setTime(1000*60*60);
System.out.println(d);
//Thu Oct 29 18:11:55 CST 2020
//Thu Jan 01 09:00:00 CST 1970
//50
//Thu Jan 01 09:00:00 CST 1970

DateFormat

時間設定成自己喜歡的格式

    Date d = new Date();
System.out.println(d);
DateFormat date = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s = date.format(d);
System.out.println(s);
String s1 = "2021年10月03日 13:41:33";
d = date.parse(s1);
System.out.println(d);

//Tue Nov 03 14:42:54 CST 2020
//2020年11月03日 14:42:54
//Sun Oct 03 13:41:33 CST 2021

Calendar

 Calendar c = Calendar.getInstance();
c.add(Calendar.MONDAY,-2);//在當前時間月份-2
c.add(Calendar.YEAR,1);//這個是年再加1
//c.set(2008,2,19);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONDAY);
int day = c.get(Calendar.DATE);
System.out.println(year+"年"+month+"月"+day+"日");
//2021年8月3日

集合

Hashmap

hashmap的長度為什麼是2的冪次方

我們首先可能會想到採用%取餘的操作來實現。但是,重點來了:“取餘(%)操作中如果除數是 2 的冪次則等價於與其除數減一的與(&)操作(也就是說 hash%length==hash&(length-1)的前提是 length 是 2 的 n 次方;)。” 並且 採用二進位制位操作 &,相對於%能夠提高運算效率,這就解釋了 HashMap 的長度為什麼是 2 的冪次方。

hashmap解決雜湊衝突

JDK1.8 之後在解決雜湊衝突時有了較大的變化,當連結串列長度大於閾值(預設為 8)(將連結串列轉換成紅黑樹前會判斷,如果當前陣列的長度小於 64,那麼會選擇先進行陣列擴容,而不是轉換為紅黑樹)時,將連結串列轉化為紅黑樹,以減少搜尋時間。

遍歷

1、Iterator

    Map<Integer,String> map = new HashMap();
map.put(1,"666");
map.put(2,"啦啦啦");
map.put(6,"哈哈");
map.put(3,"慕陽");
map.put(5,"無敵");
map.put(4,"寶貝兒");

Iterator<Map.Entry<Integer,String>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Integer,String> m = iterator.next();
// System.out.println(m.getKey()+"--"+m.getValue());
if(m.getKey() == 3){
iterator.remove();
}else {
System.out.println(m.getKey()+"--"+m.getValue());
}
}
System.out.println(map.get(3));
//1--666
//2--啦啦啦
//4--寶貝兒
//5--無敵
//6--哈哈
//null

迭代器刪除元素是安全的,在執行過程中刪除之後再遍歷就不存在之前刪除的值了

2、增強for

for(Map.Entry<Integer,String> entry: map.entrySet()){
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//1---666
//2---啦啦啦
//3---慕陽
//4---寶貝兒
//5---無敵
//6---哈哈

for(Map.Entry<Integer,String> entry: map.entrySet()){
// System.out.println(entry.getKey()+"---"+entry.getValue());
if(entry.getKey() == 3){
map.remove(entry.getKey());
}else {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
}

//1---666
//2---啦啦啦
//Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1584)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1617)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1615)
at mapdemo.MapDemo.main(MapDemo.java:29)

3、Lambda 方式

這三種效率都差不多

參考測試連結