StringBuilder
在進行大量字符串改動時(比如拼接、替換)咧织,使用String會非常消耗內(nèi)存嗓袱,降低程序性能,使用StringBuilder可以節(jié)省內(nèi)存习绢,提高程序性能
String s1 = "";
s1 += "123";
s1 += "456";
StringBuilder s2 = new StringBuilder();
s2.append("123").append("456");
由于String的不可變性渠抹,所以每次給s1賦值的時候,都是新創(chuàng)建了一個新的對象闪萄,s1指向這個新的對象梧却。所以導致String的性能較差。
- 注意败去, StringBuilder并不是String的子類放航。不過StringBuilder和String都實現(xiàn)了
CharSequence
接口
StringBuilder的常用方法有append
,insert
,delete
圆裕,replace
,reverse
等
StringBuilder的 append原理
StringBuilder的append內(nèi)部使用的是一個動態(tài)數(shù)組广鳍。默認容量是16,當容量滿時吓妆,會對數(shù)組進行擴容赊时。擴容后的新容量是原來容量的2倍加2
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
// 擴容 左移一位加上2就是新的容量
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
異常(Exception)
java中所有的異常最終都繼承自java.lang.Throwable
檢查型異常(Checked Exception)
- 這類異常一般難以避免,編譯器會進行檢查
- 如果開發(fā)者沒有處理這類異常行拢,編譯器會報錯
- 哪些異常是檢查型異常祖秒?
- 除Error、RuntimeException以外的異常
非檢查型異常(Uncheck Exception)
- 這類異常一般可以避免,編譯器不會進行檢查
- 如果開發(fā)者沒有處理這種異常竭缝,編譯器不會報錯
- 非檢查型異常:Error狐胎,RuntimeException
異常的處理
不管是檢查型異常,還是非檢查型異常歌馍,只有沒有主動處理它,都會導致java程序終止運行
異常的處理有兩種方式
- try-catch 捕獲異常
- throws 將異常往上拋
public static void main(String[] args) throws FileNotFoundException {
// 如果沒有處理異常 就會報錯
FileOutputStream fos = new FileOutputStream("F:/1.txt");
}
public static void main(String[] args) {
Integer[] nums = {11, null, 22};
for (Integer i : nums) {
System.out.println(i);
}
// 11 null 22
// 這里打印會拋出異常
for (int i : nums) {
System.out.println(i);
}
// 11
// Exception in thread "main" java.lang.NullPointerException
}
-
Integer
在自動拆箱為int
時晕鹊,會調(diào)用Integer
對象的intValue()
方法,由于nums[1]為null松却,使用null調(diào)用方法會拋出異常:java.lang.NullPointerException
finally
finally語句中的代碼一定會執(zhí)行
細節(jié): 如果在執(zhí)行try
catch
時,如果jvm推出或者當前線程被中斷溅话、殺死晓锻,finally可能不會執(zhí)行
- 如果
try
、catch
中有return
飞几、continue
砚哆、break
等結(jié)束語句,finally
會在結(jié)束語句之前執(zhí)行
try {
System.out.println("1");
return;
} finally {
// 會在return之前執(zhí)行
System.out.println("2");
}
// 1 2
for (int i = 0; i < 3; i++) {
try {
System.out.println(i + "_try_1");
if (i == 2) {
continue;
}
System.out.println(i+ "_try_2");
} finally {
System.out.println(i+ "_finally");
}
}
打印
0_try_1
0_try_2
0_finally
1_try_1
1_try_2
1_finally
2_try_1
2_finally
throws處理異常
我們還可以使用throws來拋出異常屑墨,讓上層來處理異常,如果上層不愿意處理躁锁,也可以繼續(xù)往上拋。
當拋出到jvm還沒有處理時卵史,程序就會退出
public static void main(String[] args) throws ClassNotFoundException {
test1();
}
static void test1() throws ClassNotFoundException {
test2();
}
// 拋給上層來處理異常
static void test2() throws ClassNotFoundException {
Class.forName("Abc");
}
也可以一部分異常使用try-catch
處理战转,一部分使用throws
來處理
細節(jié):
-
當父類的方法沒有
throws
異常- 子類的重寫方法也不能
throws
異常
- 子類的重寫方法也不能
-
當父類的方法有
throws
異常- 子類方法可以沒有
throws
異常 - 子類型
throws
跟父類相同類型的異常 - 也可以
throws
父類異常的子類型
- 子類方法可以沒有
throw
使用throw
可以拋出一個新建的異常
public class Person {
private int age;
public void setAge(int age) throws Exception {
if (age <= 0) {
throw new Exception("age 必須大于0");
} else {
this.age = age;
}
}
}
自定義異常
開發(fā)中自定義異常,基本都是以下兩種做法
- 繼承自
Exception
(檢查型異常)- 使用代碼復雜一些
- 希望開發(fā)者重視這個異常以躯,認真處理這個異常
- 繼承自
RuntimeException
(非檢查型異常)- 使用起來比較簡潔
- 不嚴格要求開發(fā)者去處理這個異常
public class EmptyNameException extends RuntimeException {
public EmptyNameException(){
super("name must be not empty");
}
}