問題タブ [effective-java]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Java Generics (制限されたワイルドカード)
Joshua Bloch の著書「Effective Java」によると、ジェネリクスで制限付きワイルドカードをいつどのように使用するかについてのルールがあります。このルールが PECS (Producer-Extends, Comsumer-Super) です。次の例を調べると:
このルールがこの例に完全に適合することを理解しています。pushAll
メソッドを次のサンプルとして宣言する必要があります。
しかし、次の例があるとどうなりますか?
次のように宣言する必要がpushAll
あります。
PECS規則によれば、上記の宣言は誤りです。しかし、私はStack
ofを持ち、Integer
これに渡したいStack
a Number
。なぜそれをしないのですか?
キーワード
を常に使用する必要があるのはなぜですか? extends
使い方super
が間違っているのはなぜですか?
もちろん、消費者の視点も同じです。なぜ消費者は常にあるべきなのsuper
ですか?
PS: より具体的に言うと、上記の例は、参照されている本のセクション「項目 28」にあります。
java - Collections.max() メソッドで限定されたワイルドカードが必要なのはなぜですか
Joshua Bloch による素晴らしい「Effective Java」を読みました。しかし、本の中の 1 つの例は、私には不明確なままです。ジェネリックに関する章から引用したもので、正確な項目は「項目 28: 境界付きワイルドカードを使用して API の柔軟性を高める」です。
この項目では、制限付きの型パラメーターと制限付きのワイルドカード型を使用して、コレクションから最大要素を選択するアルゴリズムの最も普遍的で防弾 (型システムの観点から) バージョンを作成する方法を示します。
記述された静的メソッドの最終的な署名は次のようになります。
Collections#max
そして、それは標準ライブラリの関数のものとほとんど同じです。
型制約で制限付きワイルドカードが必要な理由は理解できT extends Comparable<? super T>
ますが、引数の型には本当に必要なのでしょうか? List<T>
またはだけ残しても同じように思えCollection<T>
ますね。私は次のようなことを意味します:
両方の署名を使用する次のばかげた例を書きましたが、違いはありません。
では、そのような単純化された署名が受け入れられない例を提案できますか?
PSそして、なぜT extends Object
公式の実装にあるのですか?
答え
まあ、@Bohemian のおかげで、私はそれらの違いを理解することができました。
次の 2 つの補助的な方法を検討してください。
確かに、スーパークラスとそのサブクラスの両方でメソッドをオーバーロードするのはあまりスマートではありませんが、実際に推論された戻り値の型を確認できます (前points
とList<ColoredPoint>
同じです)。
どちらの方法でも、推論された型は でしたColoredPoint
。
オーバーロードされた関数に渡される型について明示したい場合があります。いくつかの方法があります。
あなたはキャストすることができます:
それでも変わらない…
または、次の構文を使用して、どの型を推論する必要があるかをコンパイラに伝えることができますclass.<type>method
。
あはは!これが答えです。ジェネリックは (配列とは異なり) 共変ではないため、List<ColoredPoint>
期待する関数に渡すことはできませんが、期待する関数に渡すことはできます。Collection<Point>
Collection<? extends Point>
そのような場合、どこで、または誰が明示的な型パラメーターを使用することを好むかはわかりませんが、少なくとも、wrongMin
不適切である可能性がある場所を示しています。
T extends Object
そして、制約の目的について回答してくれた @erickson と @tom-hawtin-tackline に感謝します。
java - 上位レベルが例外を処理する場合、下位レベルで例外をチェックする必要があります
これはEffective Javaからの引用です。
「可能であれば、下位層からの例外に対処する最善の方法は、下位層のメソッドが成功することを保証することによって、例外を回避することです。下位層に渡す前に上位レベルのメソッドのパラメーターの有効性を確認することで、これを実行できる場合があります。レイヤー。」
ハンドラーから下位レベルに伝搬される「AccessControlContext actx」というオブジェクトを考えてみましょう。「actx != null」という高レベルのチェックを行うことはできますが、低レベルでもう一度行う必要がありますか?
疑似コードの例:
質問はコメント内にネストされていますが、詳細に繰り返します。下位レベルでの冗長チェックにより、防御コーディングが保証されますが、冗長です。null を受け入れないことは Javadoc で詳しく説明されているかもしれませんが、それではバグのないコードを使用するという目的は解決されません。例外チェックを重複排除する必要がありますか?
注: これはランダムな例です。私の質問は、この例に固有のものではありません。例外をどれだけ複製するかを理解しようとする、より広範な質問です。
java - 依存オブジェクトをインスタンス変数として保存するか、ゲッターから取得した値だけを保存しますか?
3 つのゲッター「getDay、getMonth、および getYear」を持つ単純な「MyCalendar」クラスの例を考えてみましょう。「MyCalendar」オブジェクトを別のクラスに渡す場合、次のオプションのどれが適切なアプローチになるでしょうか。
オプション 1: 必要に応じて、注入されたオブジェクトのゲッターを介して必要なパラメーターを呼び出します。
また
オプション 2: 初期化の一部として、注入されたオブジェクトのゲッターから取得した値を割り当てます。
答えが選択肢 1 の場合: ループのようにフィールドに複数回アクセスする必要がある場合: for (..some imaginary usecase) { mycal.getDate(); この場合、ローカル コピーを使用するメリットはありますか?
java - 型引数にインターフェイスを使用する必要があります
可能な場合はインターフェイスを戻り値の型として使用することを強調するEffective Javaを読みました。議論を広げて、次の方法のどれが好まれるか、または良い習慣と見なされるか疑問に思っていました。
オプション1:
オプション 2:
java - Java で「equals」メソッドをオーバーライドする場合、ハッシュコードをオーバーライドする必要があるのはなぜですか?
equals
メソッドがJavaでオーバーライドされるたびに、ハッシュコードをオーバーライドする必要があることを私は知っています。それは単なる契約です。この背後にあるロジックを理解しようとしています。*Effective Java by Joshua Blochを読んでいて、このコードに出くわしました (項目 9、45 ページ):
これは彼がテキストで言及していることですが、私には理解が困難です。
この時点で、
m.get(new PhoneNumber(707, 867, 5309))
"Jenny" が返されることを期待するかもしれませんが、null が返されます。2 つの PhoneNumber インスタンスが関係していることに注意してください。PhoneNumber クラスが hashCode のオーバーライドに失敗すると、ハッシュコード コントラクトに違反して、2 つの等しいインスタンスのハッシュコードが等しくなくなります。したがって、get メソッドは、put メソッドによって格納されたハッシュ バケットとは別のハッシュ バケットで電話番号を検索する可能性があります。
彼が話している 2 つの PhoneNumber インスタンスの意味がわかりません。で作成したインスタンスのみがありますm.put(new PhoneNumber(707, 867, 5309), "Jenny")
。また、オブジェクト クラスから hashCode メソッドを継承している場合でも、同じハッシュコードを返すはずのこのオブジェクトをもう一度探します。なぜこれが起こるのですか?ここでの説明は大いに役立ちます。