【Java学習】EffectiveJava学習--第六章方法の頑丈で柔軟
方法設計の上の注意点は,可用性,頑丈性,柔軟性に焦点を当てている.
1.有効性の検査は高価であり、方法パラメータの制限は文書に記載されており、表示された検査によって制限が実施される.
2.JAVAは安全性のある言語でバッファオーバーフロー、配列境界、不正ポインタメモリエラーに対しては自動免疫するが、保護的な設計プログラムである.
コンストラクション関数の各可変パラメータは保護コピーを行うことが重要であり、保護コピー動作はパラメータの有効性を検査する前に行われ、有効性検査は元のオブジェクトではなくコピー後のオブジェクトに対して行われる.
パラメータタイプは信頼できない方子でクラス化できるので、CLONEメソッドを使用してパラメータの保護コピーを行わないでください.
攻撃されやすい書き方:
攻撃された場所は次のとおりです.
1)コンストラクション関数のDate自体は可変であり,periodをコンストラクションした後に,伝達されたendオブジェクトにおいて修正することができ,endはperiodの参照伝達であるため,periodクラス内のendも変更される.
2)アクセス方法も参照パラメータであるため,変更されることもある.
保護コピーの変更は次のとおりです.
3.内部コンポーネントが顧客に返却される前に、保護コピーを行うのも同様であり、ゼロ長でない配列は常に可変である.ゼロ以外の長さの配列は、保護コピーを行います.
または、ユーザーに配列の非可変ビューを返します.
もう1つの方法は、オブジェクトの内部コンポーネントとして非可変オブジェクトを使用することです.例えば上記の例ではDateをメンバー変数として用いるのではなくDateを用いる.gettime()のlong原語タイプ.
4.API設計技術慎重に方法の名前を選んで、便利で分かりやすくて、規範に従います. 便利な方法を追求しすぎないでください.それぞれの方法には独自の機能特徴があります. 長いパラメータリストを回避し、パラメータを間違えないようにします.(いくつかの方法、またはサブセットの方法を多く使用する) パラメータタイプで、クラスではなくインタフェースを優先的に使用します. やむを得ない限り、関数オブジェクトを少なく使用する.(文法上の混乱、機能の限界は毎回頻繁に関数オブジェクトを作成する) リロードは慎重に使用され、リロード方法の選択は静的であり、書き換え方法は動的である.
(リロードはコンパイル時に呼び出され、同じタイプがあれば上書きされ、実行時に子が親を上書きするメソッドを書き換えると子が同じメソッドが呼び出されます)
安全で保守的なポリシーは、同じパラメータ数を持つ2つのリロードメソッドを決してエクスポートしないことです.は、NULLではなくゼロ長の配列を返す.これにより、クライアント・プログラマーに余分なコードやクラッシュをもたらしやすくなります.
非ゼロ長の配列は可変であり、ゼロ長の配列は非可変である.
1.有効性の検査は高価であり、方法パラメータの制限は文書に記載されており、表示された検査によって制限が実施される.
2.JAVAは安全性のある言語でバッファオーバーフロー、配列境界、不正ポインタメモリエラーに対しては自動免疫するが、保護的な設計プログラムである.
コンストラクション関数の各可変パラメータは保護コピーを行うことが重要であり、保護コピー動作はパラメータの有効性を検査する前に行われ、有効性検査は元のオブジェクトではなくコピー後のオブジェクトに対して行われる.
パラメータタイプは信頼できない方子でクラス化できるので、CLONEメソッドを使用してパラメータの保護コピーを行わないでください.
攻撃されやすい書き方:
public final class Period {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
// TODO Auto-generated constructor stub
if(start.compareTo(end) > 0) {
throw new IllegalArgumentException(start + " after: " +end);
}
this.start = start;
this.end = end;
}
public Date start() {
return this.start;
}
public Date end(){
return this.end;
}
}
攻撃された場所は次のとおりです.
1)コンストラクション関数のDate自体は可変であり,periodをコンストラクションした後に,伝達されたendオブジェクトにおいて修正することができ,endはperiodの参照伝達であるため,periodクラス内のendも変更される.
2)アクセス方法も参照パラメータであるため,変更されることもある.
保護コピーの変更は次のとおりです.
public final class Period {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
// TODO Auto-generated constructor stub
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if(start.compareTo(end) > 0) {
throw new IllegalArgumentException(start + " after: " +end);
}
}
public Date start() {
return (Date)this.start.clone();
}
public Date end(){
return (Date)this.end.clone();
}
}
3.内部コンポーネントが顧客に返却される前に、保護コピーを行うのも同様であり、ゼロ長でない配列は常に可変である.ゼロ以外の長さの配列は、保護コピーを行います.
または、ユーザーに配列の非可変ビューを返します.
もう1つの方法は、オブジェクトの内部コンポーネントとして非可変オブジェクトを使用することです.例えば上記の例ではDateをメンバー変数として用いるのではなくDateを用いる.gettime()のlong原語タイプ.
4.API設計技術
(リロードはコンパイル時に呼び出され、同じタイプがあれば上書きされ、実行時に子が親を上書きするメソッドを書き換えると子が同じメソッドが呼び出されます)
安全で保守的なポリシーは、同じパラメータ数を持つ2つのリロードメソッドを決してエクスポートしないことです.
非ゼロ長の配列は可変であり、ゼロ長の配列は非可変である.
private List<Cheese> cheeseInstock = new ArrayList<Cheese>();
private final static Cheese[] NULL_CHEESE_ARRAY = new Cheese[0];
public Cheese[] getCheese(){
//
return (Cheese[]) cheeseInstock.toArray(NULL_CHEESE_ARRAY);
}