一般的なプログラミング
ジェネリックプログラミングとは、コードをさまざまな種類のオブジェクトで再利用できることを意味します。
型パラメーターを指定すると、継承されたプログラミングでの強制変換の安全性と可読性の問題が解決されます
基本的な概念
クラス
ジェネリッククラス:1つ以上の型変数を持つクラス。
定義:パブリッククラスのペア
型変数は、メソッドの戻り値の型と、ドメインおよびローカル変数の型を指定します
- Eコレクション要素タイプ
- キーワードのタイプとKおよびVテーブルの値
- T / U / S任意のタイプ
ジェネリック型は、型変数を具象型に置き換えることでインスタンス化でき、ジェネリッククラスは通常のクラスのファクトリーと見なすことができます
方法
定義:public static T getMiddle(T ... a)
呼び出し:ArrayAlg.getMiddle(<typeパラメーター>は省略できます。コンパイラーはそれ自体を推測し、場合によってはエラーを表示します)
タイプ制限
クラスまたはメソッド
は、Tがバインドされた型のサブタイプであることを示すために型変数を制約します
型変数またはワイルドカードには、複数の型修飾を含めることができます
。Tは、ComparableおよびSerializableを拡張します
(修飾の最大1つのクラス)。
原理
型消去
仮想マシンの場合、コンパイラーは対応するプリミティブ型(型パラメーターが削除された後の名前)、消去されたパーメーター型を提供し、それを制限型に置き換えます(非制限型変数はObjectを使用し、複数の制限型変数は最初に使用します、ラベルインターフェイスは限界の後ろに置く)
翻訳ジェネリックメソッド
メソッドの消去によって引き起こされる問題(サブクラスはジェネリックメソッドの親クラスを継承します):
- 型消去はポリモーフィズムと競合します
解決策:コンパイラ合成ブリッジメソッド(メソッド内のサブクラスの新しいパラメーター型メソッドを呼び出す) - より厳密な戻り型の問題が
解決されました:コンパイラーはブリッジメソッドを合成します(仮想マシン、パラメーター型と戻り型を使用してメソッドを決定し、コンパイラーは戻り型が異なる2つのメソッドのみを持つバイトコードを生成し、仮想マシンは正しく処理できます)
例:DateIntervalがPairを拡張し、setSecond、getSecondメソッド
をオーバーライドする使用:javacコマンドでDateIntervalクラスをコンパイルし、次にjavap -private DateIntervalコマンドを実行して逆コンパイルすると、コンパイラーによって合成されたブリッジメソッドを確認できます。
注:ブリッジメソッドの他のアプリケーション-メソッドをオーバーライドするときに、より厳密な戻り値の型を指定できます。
翻訳の一般的な表現
メソッドが総称ドメインを呼び出してアクセスすると、コンパイラーは必須の型変換を挿入します。
レガシーコードを呼び出すと警告が生成される可能性があります。アノテーション@SuppressWarnings(「未チェック」)を使用して非表示にすることができます
まとめ
- 仮想マシンにはジェネリックはなく、通常のクラスとメソッドのみです。
- すべての型パラメーターは、修飾された型に置き換えられます。
- ブリッジ法は、ポリモーフィズムを維持するために合成されます。
- 型の安全性を維持するために、必要に応じて必須の型変換が挿入されます。
使用制限
主に型の消去が原因
- 基本型で型パラメーターをインスタンス化することはできません
- ランタイム型クエリはプリミティブ型にのみ適用されます
- パラメーター化された型の配列を作成できません(変数の宣言は有効です)
型の消去。異なる型のパラメーターの無関係なインスタンスを同じ配列に追加し、内部ロジックエラーを引き起こす可能性があります - varargs警告
可変数のパラメーターを持つメソッドがジェネリック型のインスタンスで渡されます。ルールは緩和されていますが、@ SafeVarargsまたは@SuppressWarningsを追加する必要があると警告されます - 型変数をインスタンス化できません
解決策:静的ペアmakePair(サプライヤーconstr)またはClass.newInstance() - ジェネリック配列を作成できません
- 配列がクラスのプライベートインスタンスドメインとしてのみ使用される場合は、Object []として宣言でき、要素を取得するときに強制変換が実行されます。
- ユーザーは配列コンストラクター式
public static <T extends Comparable> T [] minmax(IntFunction constr、T…a)を提供します{T port mm = constr.apply(2);}
String [] ::新規
または使用法: Array.newInstance
アプリケーション:ArrayList.toArray
- ジェネリッククラスの静的コンテキストの型変数が無効です
- ジェネリッククラスインスタンスをスローまたはキャッチできません
- チェックした異常の検査を排除できます
- 消去後の競合に注意してください
- メソッドの命名に注意してください
- 「消去の変換をサポートする場合は、クラスまたはタイプ変数が同時に2つのインターフェースタイプのサブクラスにならないようにする必要があります。これらの2つのインターフェースは、同じインターフェースの異なるパラメーター化です。」
継承ルール
- SとTの接続に関係なく、通常、Paiは
Pairとは接続していません。 - パラメータ化された型をプリミティブ型に変換できます
- 総称クラスは、他の総称クラスを拡張または実装できます
ワイルドカードタイプ
コンセプト
ジェネリックを使用する場合、パラメーターのタイプを変更できるジェネリックタイプは、ワイルドカードタイプと呼ばれます。
public static void printBuddies(Pair p)は
、このメソッドにPairを渡すことはできませんが、パラメーターを
Pairに変更した後<?extends Employee>
制限別
-
タイプ
Pair <?Extends Employee>のサブタイプ修飾変数は、そのsetFirstメソッドを呼び出すことができません。コンパイラーは、特定のタイプ
を渡して、安全なアクセサーメソッドと安全でないチェンジャーメソッドを区別することを拒否します。 -
スーパータイプで修飾されたサブタイプの境界
は、メソッドにパラメーターを提供できますが、戻り値を使用できません -
修飾されて
いないワイルドカードは実際のタイプを必要としません
ワイルドカードキャプチャ
ワイルドカードのキャプチャは、多くの制限がある場合にのみ有効です
リフレクションとジェネリック
ジェネリッククラス
これにより、ClaSSメソッドの戻り型をよりターゲットに絞ることができます
T newInstanceO
T cast(Object obj)
T getEnumConstants()
Class <?Super T> getSuperclass()
コンストラクタgetConstructor(C1ass…parameterTypes)
コンストラクタgetDeclaredConstructor(Class…parameterTypes)
仮想マシンの情報
TypeVariable:タイプ変数
WildcardType:ワイルドカードで修飾された
ParameterizedType:ジェネリッククラスまたはインターフェイスタイプ(Comparable <?Super T>など)
GenericArrayTYpe:ジェネリック配列タイプ
コレクション
コレクションフレームワーク
基本構造
Iterable
Iterator:hasNext、next、remove、forEachRemaining
Collection:追加、反復子、汎用ユーティリティメソッド
AbstractCollection:一部のメソッドのデフォルト実装を提供します
Listインターフェース:ランダムアクセスの複数のメソッドを定義します
ListIterator:イテレーターの前に要素を追加するメソッドを定義します
RandomAccess:ラベルインターフェース、コレクション実装クラスが効率的なランダムアクセスメソッドをサポートするかどうかを識別します
Setインターフェース:Collectionと同等ですが、すべてのセットがコレクションであるとは限りません。プログラマがセットのみを受け入れるメソッドを書くと便利です。
SortedSet、SortedMap:コレクションのサブセットビューを取得するメソッドを定義します。(9.4)
NavigableSet、NavigableMap:順序付けられたセットとマップを検索およびトラバースするためのメソッド、TreeSet、TreeMap実装
特定のコレクション
-
リンク
リスト配列および配列リストの主な欠点:途中で要素を挿入または削除すると、大きな代償が発生します(リンクリストを使用する唯一の理由)。
すべてのリンクリストは、実際には二重リンクです。ListIteratorインターフェイスは、逆の操作方法を定義します- 要素の追加
位置依存のaddメソッドは、イテレータの役割です。イテレータを使用して、要素を自然順序付けされたコレクションに追加することは理にかなっています。すべてのaddメソッドは、
要素を前方または後方に挿入するためにListIteratorで定義されています。挿入位置の数はn +1 - トラバース
逆トラバーサル:hasPrevious、前の
ランダムアクセス方式、低効率を使用して、リストをトラバースしません - 削除
前方または後方に削除できます
- 要素の追加
-
配列リスト
-
ハッシュセット
負荷係数は、ハッシュテーブルをいつ再ハッシュするかを決定します。テーブル内の位置の75%以上が要素で満たされており、テーブルはバケットの2倍の数で自動的に再
ハッシュされますHashSet:ハッシュテーブルセット
JavaSE8に基づいて、バケットがいっぱいになると、リンクされたリストのプログラミングからバイナリツリーのバランスが取られます -
ツリーが設定され
(現在の実装では、赤、黒の木を使用しています)TreeSetのソートを完了するために、ツリー構造を使用して順序付きコレクション(分別収集)である、のNavigableSetを実現しました。
セット内の要素をソートする必要がない場合は、ハッシュセットが推奨されます。 -
キュー
取得ルール:先入れ先出し
実装:循環配列、リンクリスト
ArrayDeque:制限付きの制限付きコレクション容量
LinkedList:制限なしのコレクション -
優先度キュー
は任意の順序で挿入され、並べ替えられた順序で取得されます。また、removeメソッドが呼び出され、常に現在のキューで最も低い優先度を持つ要素が取得されます。
ソートせずに要素を繰り返し処理します。
構造:ヒープの
使用例:タスクスケジューリング
地図
-
共通実装クラス
HashMap
TreeMap -
操作が
置か-キーパラメータの格納された値でこの戻り
、更新用地図
counts.put(ワード、counts.getOrDefault(ワード 0)+ 1);
又は
counts.putlfAbsent(ワード、0);
counts.put(ワード、カウント.get(word)+ 1); // getが成功
または
counts.merge(word、1、Integer :: sum); -
マップビューの
keySet、values、entrySet
は要素を削除できますが、addを呼び出して要素を追加することはできません -
プライベートマッピング
- WeakHashMap:キーへの唯一の参照がハッシュエントリからのものである場合、このデータ構造はガベージコレクターと連携してキーと値のペアを削除します。
- LinkedHashSetおよびLinkedHashMap:
①エントリがテーブルに挿入されると、二重リンクリストにマージされます。挿入されたアイテムの順序を覚えておいてください。
②リンクハッシュマップは、アクセスオーダーを使用してマッピングエントリを反復できます。getまたはputが呼び出されるたびに、影響を受けるエントリが現在の位置から削除され、リンクされたエントリのリストの最後に配置されますLinkedHashMap <K、V>(initialCapacity、loadFactor、true)③removeEldestEntry
メソッドをオーバーライドして、「アクセス順序に基づく」を実装できますキャッシングを実現するための「最も最近使用されていない」原則 - EnumSet、EnumMap:キーは列挙型であり、セットは静的メソッドを使用して構築できます
- IdentityHashMap:System.identityHashCode計算キー、オブジェクトを比較する場合は==を使用
ビューとラッパー
-
軽量コレクションラッパー
Arrays.asList()
Collection.nCopies(100、 "xx")
Collection.singleton()/ singletonList / singletonMap -
サブレンジは
任意の操作を適用できます -
変更することはできません
Collections.unmodifiableCollection / xxxList / xxxSet ...... -
同期
-
チェックされたビュー
要素を追加するときに、定義されたジェネリック型を満たしているかどうかを確認します
アルゴリズム
- 並べ替え
- 二分探索
- 単純なアルゴリズムの
最小、最大、... - バッチ操作
addAll、retainAll、... - 配列変換
レガシーコレクション
- ハッシュ表
- 列挙
- プロパティのマッピング
- 積み重ね
- ビットセット
まとめ
この記事では、Javaコアテクノロジのジェネリックとコレクションの内容を整理します。Javaでのジェネリックの実装はコンパイラの機能です。型の消去はジェネリックが定義されている場所で行われ、強制的な型変換はジェネリックが使用されている場所に挿入されます。クラス定義が多すぎるという問題を解決するために、Java言語のセキュリティが強化されます。コレクションフレームワークは、豊富なインターフェースと実装クラス、および関数開発を提供し、ジェネリックの特定のアプリケーションを反映します。
詳細については、私の公開アカウントに注目してください。