effectiveJava學習筆記:通用程式設計(一)
將區域性變數的作用域最小化
其實大部分人還是在第一次使用變數的時候宣告變數的,在開頭就將所有變數宣告的還沒見過。
要使區域性變數的作用域最小化,最有力的方法就是在第一次使用它的地方宣告。
但是,這裡書中講到了for迴圈優於while迴圈,值得我們注意。
for迴圈將變數宣告在迴圈內,不會在後面引起手殘的錯誤。
for (Element e : c) { doSomething(e); } for (Interator i = c.iterator(); i.hasNext();) { doSomething((Element)i.next()); }
但是while變數在外面,如果變數一多,就容易不小心引發錯誤。
List<string> list =new ArrayList<string>();
while (list.iterator().hasNext()) {
list.iterator().next();
}
for-each迴圈優先於for迴圈
首先,for-each比for迴圈要優雅簡潔的多,一眼就能看的明明白白,其次不容易寫錯。
for-each迴圈在預防Bug方面有著傳統的for迴圈無法比擬的優勢,並且沒有效能損失。應該儘可能的使用for-each迴圈。遺憾的是,有三種常見的情況無法使用for-each迴圈:
- 過濾——如果需要遍歷集合,並刪除選定的元素,就需要使用顯示的迭代器,以便可以呼叫他的remove方法。
- 轉換——如果需要遍歷列表或者陣列,並取代他部分或者全部的元素值,就需要列表迭代器或者陣列索引,以便設定元素的值。
- 平行迭代——如果需要並行的遍歷多個集合,就需要顯式的控制迭代器或者索引變數,以便所有迭代器或者索引變數都可以得到同步前移。
大致對我們來講就是除了刪除元素和需要索引,用for-each沒什麼問題。
使用庫類沒啥說的,標準庫類都是大牛寫的,如果你沒有強烈的自信和興趣,還是使用庫類把。
如果需要精確的答案,請避免使用float和double
double和float都是科學計算,就是不保證精度的。
public class Item48 {
public static void main(String[] args) {
System.out.println(1.03-.42);
}
}
結果是0.6100000000000001
float和double型別主要是為了科學計算與工程計算而設計的,它們並沒有提供完全精確的結果,所以不應該被用於需要精確結果的場合。在商業計算中要用BigDecimal。BigDecimal所建立的是物件,我們不能使用傳統的+、-、*、/等算術運算子直接對其物件進行數學運算,而必須呼叫其相對應的方法。
2.構造器描述
BigDecimal(int) 建立一個具有引數所指定整數值的物件
BigDecimal(double) 建立一個具有引數所指定雙精度值的物件
BigDecimal(long) 建立一個具有引數所指定長整數值的物件
BigDecimal(String) 建立一個具有引數所指定以字串表示的數值的物件
3.方法描述
add(BigDecimal) BigDecimal物件中的值相加,然後返回這個物件
subtract(BigDecimal) BigDecimal物件中的值相減,然後返回這個物件
multiply(BigDecimal) BigDecimal物件中的值相乘,然後返回這個物件
divide(BigDecimal) BigDecimal物件中的值相除,然後返回這個物件
toString() 將BigDecimal物件的數值轉換成字串
doubleValue() 將BigDecimal物件中的值以雙精度數返回
floatValue() 將BigDecimal物件中的值以單精度數返回
longValue() 將BigDecimal物件中的值以長整數返回
intValue() 將BigDecimal物件中的值以整數返回
4.BigDecimal比較
BigDecimal是通過使用compareTo(BigDecimal)來比較的
5.BigDecimal缺點
與使用基本運算型別想比,這樣做很不方便
效能比double和float差,在處理龐大,複雜的運算時尤為明顯。
但是為了保證精度必要時可以使用。
基本型別優先於裝箱基本型別
在基本型別和裝箱基本型別中有3個主要區別:
1、基本型別只有值,裝箱基本型別具有與它們的值不同的統一性,就是兩個裝箱基本型別可以具有相同的值和不同的同一性。
2、基本型別只有功能完備的值,而每個裝箱基本型別除了它對應基本型別的所有功能值外,還有個非功能值–null;
3、基本型別比裝箱基本型別更節省時間和空間。
1、對裝箱基本型別執行 = 幾乎都是錯誤的,因為他們的值相同的時候同一性不相同。
2、
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if (i == 42) {
System.out.println("Unbelievable");
}
}
}
會得到一個NullPointerException異常。
3、這個程式執行起來比預期的要慢一些,因為不小心將區域性變數sum宣告成了裝箱基本型別Long,程式編譯起來沒有警告或者錯誤,但是變數被反覆的裝箱和拆箱,導致效能明顯下降
這個在之前也講過
public static void main(String[] args) {
Long sum = 0L;
long startTime = System.currentTimeMillis();
for(long i = 0;i<Integer.MAX_VALUE;i++) {
sum += i;
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - startTime);
}
可以試一下Long和long的時間相差多少。
如果其他型別更合適,則儘量避免使用字串
1.字串不適合代替其他的值型別。只有當資料確實是文字資訊時,才應該使用字串,如果是數值,就應該被轉換為適當的數值型別,如果是一個“是-或-否”的問題答案,應該被轉換為boolean型別,如果是一個物件,應該使用物件引用來引用它。
2.字串不適合代替列舉型別:列舉型別比字串更加適合用來表示列舉型別的常量。
3.字串不適合代替聚集型別。如果一個實體有多個元件,用字串來表示這個實體通常不恰當,String compundKey = className + "#" + i.next();
更好的做法是編寫一個類來描述這個資料集,通常是一個私有的靜態成員類。
4.字串不適合代替能力表(暫時沒看懂)