你是否曾經在面試的時候,常常被問到:數組有沒有 length() 方法?字符串有沒有 length() 方法? 集合有沒有 length() 方法?面試
面對這個問題,那麼不得不吐槽一下,Java 中獲取長度的方式,設計着實有點亂,對剛入門的程序猿而言,那絕對是一臉的懵逼。編程
String[] array = {"abc", "def"};
String str = "abcedf";
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
System.out.println("數組的長度: " + array.length);
System.out.println("字符串的長度: " + str.length());
System.out.println("集合的長度: " + list.size());
複製代碼
正式科普一下,但願可以銘記你心中。數組求長度用 length 屬性;字符串求長度用 length() 方法;集合求長度用 size() 方法。數組
對於程序猿來講,編程規範可以養成良好的編程習慣,提升代碼質量,減小溝通成本。阿里 Java 開發手冊編程規約中記載,【強制】方法名、參數名、成員變量、局部變量都統一使用 lowerCamelCase 風格,必須聽從駝峯形式。bash
看到這裏,不得不提 String 中的 substring 方法,你是否是常常把「substring」寫成「subString」。本次這個命名不是吐槽的重點。主要想分享以下代碼片斷。ui
public class StringInterview {
public static void main(String[] args) {
String str = "......abcdefgh.......";
String subStr = str.substring(1,3);
str = null;
System.out.println(subStr);
}
}
複製代碼
假如上述這段程序在 Java 1.6 中運行,代碼中雖然強制使 str 引用爲空,本意是釋放 str 佔用的空間,可是這個時候,GC 是沒法回收這個大的 char 數組的,由於還在被 subStr 字符串內部引用着,雖然 subStr 只截取這個大數組的一小部分。當 str 是一個很是大字符串的時候,這種浪費是很是明顯的,甚至會帶來內存泄露問題。this
深刻 Java 1.6 中 substring 的設計一探究竟。編碼
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
。。 。。 。。
}
if (endIndex > count) {
。。 。。 。。
}
if (beginIndex > endIndex) {
。。 。。 。。
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
複製代碼
到此你應該撥雲見日豁然開朗。當咱們調用字符串 str 的 substring 獲得字符串 subStr,其實這個操做,無非就是調整了一下 subStr 的 offset 和 count ,用到的內容仍是 str 以前的 value 字符數組,並無從新建立新的專屬於 subStr 的內容字符數組。若是 subStr 的生命週期要長於 str 或者手動設置 str 爲null,當垃圾回收進行後,str 被回收掉,subStr 沒有回收掉,那麼內存佔用依舊存在,由於 subStr 持有 str 字符數組的引用。spa
正式科普一下,這個問題出如今 Java 1.6,而且 Java 1.7 中已經修復。雖然已經修復,並不表明咱們就不須要了解,若是你正在求職路上,稍微瞭解一下,說不定會加分。設計
先給各位拋一段 Java LinkedList 類的代碼片斷,一塊兒吐槽吐槽。code
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
複製代碼
JDK 中 if 語句後只有一條語句,大部分都是這麼實現的。原則上,if 語句若是後面跟着只有一句話,是能夠不加的。可是在咱們實際開發中,有些現象卻會讓你匪夷所思,不信你看看下面的代碼片斷。 片斷一:
if (f == null)
//拋出異常,或者加一條打印語句,加上此句註釋邏輯就變了
throw new NoSuchElementException();
複製代碼
片斷二:
public class Interview {
public static void main(String[] args) {
Class c = Interview.class;
try {
Object o = c.newInstance();
if (o instanceof Interview)
Interview tt = (Interview) o; //爲何會報錯?請各位解釋緣由
} catch (Exception e) {
e.printStackTrace();
}
}
}
複製代碼
正式科普一下,看似一個簡單的編碼規範,背後隱藏了多少坑啊,因此爲了良好的編程習慣,建議仍是統一加上大括號爲好,良好的編碼習慣是真重要啊。
Tiago Fernandez 作過一次投票,選舉最爛的 Java API,排第二的就是日期 API(Date 和Calender)。一言不合就拋代碼,以下片斷是計算兩個日期之間的天數。
public static void main(String[] args) {
Calendar begin = Calendar.getInstance();
begin.set(1990, Calendar.JUNE, 17);
Calendar end = Calendar.getInstance();
System.out.println(alculatedDays(begin, end));
System.out.println(alculatedDays(begin, end)); // 爲何顯示 0?
}
複製代碼
public static long alculatedDays(Calendar begin, Calendar end) {
long days = 0;
while (begin.before(end)) {
begin.add(Calendar.DAY_OF_MONTH, 1);
days++;
}
return days;
}
複製代碼
alculatedDays 方法,若是連續計算兩個 Date 實例的話,第二次會取得 0,由於 Calendar 狀態是可變的,考慮到重複計算的場合,最好複製一個新的 Calendar,改造以下
public static long alculatedDays(Calendar begin, Calendar end) {
Calendar calendar = (Calendar) begin.clone(); // 複製
long days = 0;
while (calendar.before(end)) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
days++;
}
return days;
}
複製代碼
不過萬物都在向前進化,由於因爲原來老舊的日期 API 一直被人詬病,因此 JDK 1.8 中對日期的改動是特別大的,基本上是引入了一套全新易用的 API,各位有時間能夠體驗一下。
好了,吐槽中見真諦,今天就講這麼多吧。但願你能 get 到一點點共鳴,若是你比較感興趣,就多多關注和分享給身邊的朋友吧。