1, 不可變 String
String 對象時不可變的 .String類中每一個看起來會修改String值得方法, 實際上都是創建一個全新的String對象 .
2, 重載 "+" 與 StringBuilder類.
2.1 "+" 和 "+="運算符
Java只重載了 "+" 和 "+="
這兩個操作符,而且 Java 不允許程序員重載任何運算符 . Java在重載這兩個運算符時自動創建一個StringBuilder
類的實例對象,然后使用append()
方法將字符串組裝起來.
2.2 StringBuilder類.
一個可變的字符序列,此類提供一個和StringBuffer
兼容的API,但是 StringBuilder不是線程安全的 . 因此StringBuilder
的效率要比StringBuffer
高.使用率也較高.
如果需要處理多線程同步問題則建議使用StringBuffer
類.
注意 1 : 編譯器優化問題
如果字符串操作比較簡單那么可以使用
String
類,編譯器會自動進行優化,但是如果有循環則必須自己創建StringBuilder
否則編譯器會在每個循環內創建一個StringBuilder
這樣的話效率低.
注意 2 : 無意識遞歸問題
// 測試類
public class InfiniteRecursion {
// 重寫 String 方法.
@Override
public String toString(){
return "InfiniteRecursion address : " + this + '\n';
}
// mian 方法.
public static void main(String[] args){
InfiniteRecursion i = new InfiniteRecursion();
System.out.println(i);
}
}
上述代碼執行后會產生堆棧溢出錯誤 :
Exception in thread "main" java.lang.StackOverflowError
at java.lang.String.length(String.java:623)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:414)
at java.lang.StringBuilder.append(StringBuilder.java:132)
at java.lang.StringBuilder.<init>(StringBuilder.java:110)
原因就是在這句"InfiniteRecursion address : " + this + '\n'
代碼上,因為想要打印對象的內存地址而使用了 this
關鍵字. 但是 this
和 字符串
相加就會導致會將 this
強轉成 String
類型也就是會調用 this
的 toString
方法, 也就出現了循環引用問題. 因此,此處不應該使用 this
而應該使用 super.toString()
.
3, 格式化輸出
3.1 System.out.format()
Java SE5 引入了 format()
方法可用于 PrintStream
和 PrintWrite
對象.其中也包括System.out
對象.
示例代碼 1 :
public class SimpleFormat {
public static void main(String[] args){
int x = 5;
double y = 5.11111;
// 方式一
System.out.println("x : " + x + " y : " + y);
// 方式二
System.out.format("x : %d y : %f\n",x,y);
// 方式三
System.out.printf("x : %d y : %f\n",x,y);
}
// 輸出
/*
x : 5 y : 5.11111
x : 5 y : 5.111110
x : 5 y : 5.111110
*/
}
3.2 Formater 類
在 Java中 所有新的格式化功能都是由Formater類處理的 .具體使用可以查看JDK文檔.
3.3 格式化說明符
抽象語法 :%[argument_index$][flag][width][.precision]conversion
-
width
: 用來設置最小寬度. -
pricision
: 設置最大寬度, (打印String
表示最多字符數、打印浮點數
小數點后的位數,不足則補零,多了進行四舍五入操作. - 最常用的格式化控制符如下 :
符號 | 含義 |
---|---|
d | 整數(十進制) |
c | Unicode 字符 |
b | Boolean 值 |
s | String |
f | 浮點數(十進制) |
e | 浮點數(科學計數) |
x | 整數(十六進制) |
h | 散列碼(十六進制) |
% | 字符 %
|
3.4 String.format() 獲取格式化字符串
Java SE5 中引入了 String.format()
方法 , 當只需要使用 format()
一次的情況可以使用 String.format()
.
3.5 十六進制轉儲工具
// 格式化工具類.
public class Hex {
// 格式化方法.
public static String format(final byte[] data) {
StringBuilder sb = new StringBuilder();
int address = 0;
for (byte b : data) {
// 每行顯示 16 個數據.
if (address % 16 == 0) {
sb.append(String.format("%05X : ", address));
}
// 保存數據
sb.append(String.format("%02X ", b));
address ++;
// 判斷是否是行尾
if (address % 16 == 0){
sb.append('\n');
}
}
sb.append('\n');
return sb.toString();
}
// 測試函數
public static void main(String[] args) {
final byte[] bs = new byte[100];
Arrays.fill(bs, (byte)1);
System.out.println(Hex.format(bs));
}
// 輸出結果.
/*
00000 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00010 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00020 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00030 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00040 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00050 : 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
00060 : 01 01 01 01
*/
}
4, 掃描輸入類 Scanner
一個可以使用正則表達式來解析基本類型和字符串的簡單文本掃描器.Scanner 使用分隔符模式將其輸入分解為標記,默認情況下該分隔符模式與空白匹配.然后可以使用不同的 next 方法將得到的標記轉換為不同類型的值.
// 從 System.in 中讀取一個整數 .
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
// 掃描器還可以使用不同于空白的分隔符
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();
// 使用正則表達式同時解析所有的 4 個標記
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input);
s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
MatchResult result = s.match();
for (int i=1; i<=result.groupCount(); i++)
System.out.println(result.group(i));
s.close();