Java經典的書籍有幾本,都是很多有經驗的開發人員推薦的,包括Java編程思想,深入理解Java虛擬機,Java核心技術和Effective Java。工作之後發現自己讀的技術書籍少的可憐,因爲不愛讀書,很多基礎的知識都忘了。從最近開始,打算好好的看書,把這些經典的書籍好好的看一遍,把重要的內容記下來。以下是Effective Java的讀書筆記:
第一章 引言
這本書講解了78個條目的,每個條目討論一條規則,從第二章開始講解。
第二章 創建和銷燬對象
第1條: 考慮用靜態工廠方法代替構造器
優點:1. 與構造器不同的第一大優勢在於,它們有名稱;
2. 與構造器不同的第二大優勢在於,不必在每次調用它們的時候都創建一個新對象;
3. 與構造器不同的第三大優勢在於,它們可以返回原返回類型的任何子類型的對象;
4. 在創建參數化類型實例的時候,它們使代碼變得更加簡潔
缺點:1. 類如果不含公有的或受保護的構造器,就不能被子類化
2. 它們與其他的靜態方法實際上沒有任何區別
例子如下:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Services {
private Services(){
}
private static final Map<String, Provider> providers =
new ConcurrentHashMap<String, Provider>();
public static final String DEFAULT_PROVIDER_NAME = "<def>";
public static void registerDefaultProvider(Provider p){
registerProvider(DEFAULT_PROVIDER_NAME ,p);
}
public static void registerProvider(String name, Provider p){
providers.put(name, p);
}
public static Service newInstance(){
return newInstance(DEFAULT_PROVIDER_NAME);
}
public static Service newInstance(String name){
Provider p = providers.get(name);
if(p == null){
throw new IllegalArgumentException(
No provider registered with name: + name);
}
return p.newService();
}
}
第2條: 遇到多個構造器參數是要考慮用構建器(靜態工廠和構造器有個共同的侷限性:它們不能很好的擴展到大量的可選參數)
如下是幾種方法來創建類的對象
重疊構造器模式
例子如下
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
}
public NutritionFacts(int servingSize, int servings, int calories) {
this(servingSize, servings, calories, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat) {
this(servingSize, servings, calories, fat, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat,
int sodium) {
this(servingSize, servings, calories, fat, sodium, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat,
int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
}
JavaBean模式
例子如下:
public class NutritionFacts {
private int servingSize = -1;
private int servings = -1;
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public NutritionFacts() {
}
public void setServingSize(int servingSize) {
this.servingSize = servingSize;
}
public void setServings(int servings) {
this.servings = servings;
}
public void setCalories(int calories) {
this.calories = calories;
}
public void setFat(int fat) {
this.fat = fat;
}
public void setSodium(int sodium) {
this.sodium = sodium;
}
public void setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
}
}
Builder模式(創建器模式)
例子如下:
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder{
private final int servingSize;
private final int servings;
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val){
calories = val;
return this;
}
public Builder fat(int val){
fat = val;
return this;
}
public Builder carbohydrate(int val){
carbohydrate = val;
return this;
}
public Builder sodium(int val){
sodium = val;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
對於構造器或者靜態工廠中具有多個參數,設計這種類的時,builder模式就是種不錯的選擇
比重疊構造器模式比,它的客戶端代碼將更易於閱讀和編寫
比JavaBean更加安全
第3條: 用私有構造器或者枚舉類型強化Singleton屬性
單例模式的2種用法(jdk1.5之前)
1. 公有靜態成員是final域
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis(){
}
public void leaveTheBuilding(){
}
}
2. 公有成員是個靜態工廠方法
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis(){
}
public static Elvis getInstance(){
return INSTANCE;
}
public void leaveTheBuilding(){
}
}
3. 編寫一個包含單個元素的枚舉類型
enum Elvis {
INSTANCE;
public void leaveTheBuilding(){
System.out.println("leaveTheBuilding......");
}
}
public class A{
public void get(){
Elvis.INSTANCE.leaveTheBuilding();
}
public static void main(String[] args){
A a = new A();
a.get();
}
}
第4條: 通過私有構造器強化不可實例化的能力
編寫只包含靜態方法和靜態域的類,這樣的類要求不能被實例化,這時候就可以通過把構造器定義爲私有類型就可以了,(Java裏的一些工具類不希望被實例化)
public class UtilityClass {
private UtilityClass(){
throw new AssertionError();
}
}
AssertionError是爲了防止類內部調用構造器。