[学习摘要] Effective java [EN 3rd version] (Item 1-5)

为了便于复习,记录了一些对Effective java 英文版学习过程中的一些 理解和要点摘抄,想快速学习的小伙伴 可以参考其中的要点。要点摘抄的比较全面。

 

1. Consider static factory methods instead of constructors

 

Advantages of static factory methods:

1. unlike constructors, they have names

2. unlike constructors, they are not required to create a new object each time they’re invoked

3. unlike constructors, they can return an object of any subtype of their return type.

4. the class of the returned object can vary from call to call as a function of the input parameters

5. the class of the returned object need not exist when the class containing the method is written

 

This list is far from exhaustive:// so many kinds of "get instance"

that incorporates them, for example:

Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);


• valueOf—A more verbose alternative to from and of, for example:
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);


• instance or getInstance—Returns an instance that is described by its
parameters (if any) but cannot be said to have the same value, for example:
StackWalker luke = StackWalker.getInstance(options);


• create or newInstance—Like instance or getInstance, except
that the method guarantees that each call returns a new instance, for example:
Object newArray = Array.newInstance(classObject, arrayLen);


• getType—Like getInstance, but used if the factory method is in a
different class. Type is the type of object returned by the factory method, for
example:
FileStore fs = Files.getFileStore(path);


• newType—Like newInstance, but used if the factory method is in a
different class. Type is the type of object returned by the factory method, for
example:
BufferedReader br = Files.newBufferedReader(path);


• type—A concise alternative to getType and newType, for example:
List<Complaint> litany = Collections.list(legacyLitany);

 

 

2.Considera builder when faced with many constructor parameters

 

In traditionaly ,we make many constructors with different amount of  parameters .

in which you provide a constructor with only the required parameters, another with a single optional parameter, a third with two optional parameters, and so on, culminating in a constructor with all the optional parameters.

it is like:(这种写法, 难写,难看)

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);
}

 

There is an anather choice which is use setter function

A second alternative when you’re faced with many optional parameters in a constructor is the JavaBeans pattern, in which you call a parameterless constructor to create the object and then call setter methods to set each required parameter and each optional parameter of interest: (这种写法 无法保证原子性)

public NutritionFacts() { }
// Setters
public void setServingSize(int val) { servingSize = val; }
public void setServings(int val) { servings = val; }
public void setCalories(int val) { calories = val; }
public void setFat(int val) { fat = val; }

 

better way is use builder

Instead of making the desired object directly, the client calls a constructor (or static factory) with all of the required parameters and gets a builder object. Then the client calls setter-like methods on the builder object to set each optional parameter of interest. 

Finally, the client calls a parameterless build method to generate the object, which is typically immutable.

// Builder Pattern
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 {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbohydrate = 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 sodium(int val)
            { sodium = val; return this; }
        public Builder carbohydrate(int val)
            { carbohydrate = 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;
    }
}


//====================================================
//user builder build new obj

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100).sodium(35).carbohydrate(27).build();
//执行顺序,从前至后,最后通过build() 生成NutritionFacts类型对象,因而在对象生成之前,
//setter 完全连续,NutritionFacts 对象也不会再创建的过程中被其他线程调用

之后 NutritionFacts  类还可以被继承,子类可以进一步扩展 返回builder 的函数种类 ,并且修改为返回子类对象,有比较好的扩展性。(!!!最好,原始类写成虚函数!!!)

eg.

public class myNu extends NutritionFacts {
    private final  int HaHa ;  
 
    public static class Builder extends NutritionFacts.Builder<Builder> {
        private int HaHa ;        
        public Builder sethaha(int a) 
        {
            this.HaHa = a;
            return this;
        }

        @Override 
        public builder(int servingSize, int servings) {
            super(servingSize, servings)
        }
        
        @Override 
        public myNu build() {
            return new myNu (this);
        }

    }

    private myNu (Builder builder) {
        super(builder);
        HaHa = builder.HaHa ;
    }

}
    
//=====================
myNu mNu = new myNu.Builder(240, 8). calories(100).sodium(35).carbohydrate(27).sethaha(6).build();

A builder can fill in some fields automatically upon object creation, such as a serial number that increases each time an object is created.(注意 builder 必须是类的静态内部类,他可以维护一些在创建对象的过程中动态变化的数值的赋值。例如,随着对象创建自增的数,等。)

 


3 . Enforce the singleton property with a private constructor or an enum type

 

there are two mothods of sigleton 

one is Singleton with public final field :

public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}

second is Singleton with static factory,  in this situation ,the field is private :

public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() { ... }
}

third way is Enum singleton - the preferred approach 
This approach is similar to the public field approach

public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}

a single-element enum type is often the best way to implement a singleton. (直接把Elvis类 写成一个enum ,是最安全简洁的方法)

question !!说是可以防止反射攻击,但是另外两种方法的构造函数是private,怎么反射攻击呢 ?

!!! Note that you can’t use this approach if your singleton must extend a superclass other than Enum
(though you can declare an enum to implement interfaces).

 

word remind:

constructors构造器( constructor的名词复数 )
stick out like a sore thumb显得别扭
serializable可串行化的
similar to跟。。。类似得,与。。。同样的; 如同
serialization连载长篇
for free免费
ironclad装甲的; <美>严格的; 装甲舰
guarantee against保证…不…
instantiation实例化,例示
in the face of面对

reflection attacks. 反射攻击。
Enforce  强制执行
noninstantiability  不稳定性
reputation            名声
primitive    原始的
instantiated    实例化
This idiom is mildly counterintuitive 这个成语有点违反直觉

 

 

4 .  Enforce noninstantiability with a private constructor
(用私有构造函数 实现类的强制不可实例化)

question1 : (Why the private constructor cannot be invoked? 接上面的反射攻击)答案:如下图,构造函数中抛出不可调用异常,防止反射调用~。

attention !!  the class which has private constructor can not be subclassed . All constructors must invoke a superclass constructor, explicitly or implicitly, and a subclass would have no accessible superclass constructor to invoke.

// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
} ... // Remainder omitted
}
word remind :

the constructor is provided expressly so that it cannot be invoked.构造函数是明确提供的,因utility此无法调用它。
it’s not uncommon to see这并不少见
Prefer dependency injection to hardwiring resources比起硬连接资源,更喜欢依赖注入
instantiable可实例化
underlying潜在的
arbitrary任意的
It preserves immutability variant

 

 

5.  Prefer dependency injection to hardwiring resources

 

(用依赖注入取代 硬连接)

assume there is more and more dictionaries underlying .
stop using static class or singletons to implement as :  private final Lexicon dictionary = a,b,c,d,...;

Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.(当函数的行为由某个参数决定是,考虑多对象,用此参数作为建立对象的依据)

具体实现方法:pass the resource into the constructor when creating a new instance.

// Dependency injection provides flexibility and testability
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) { ... }
public List<String> suggestions(String typo) { ... }
}

Dependency injection is equally applicable to constructors, static factories (Item 1), and builders(item2).

the dependency work It preserves immutability

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值