汎用-基本概念(一)

6024 ワード

これは汎用汎用型であり、プログラム設計言語の特性である.プログラマが強いタイプのプログラム設計言語でコードを記述するときに、使用前に示す必要があるいくつかの可変部分を定義することを許可します.さまざまなプログラミング言語は、コンパイラ、実行環境の汎用的なサポートとは異なります.タイプをパラメータ化して、コード多重化を達成し、ソフトウェア開発の生産性を向上させるデータ型です.1つの汎用タイプは、1つ以上のタイプ変数を使用して定義され、1つ以上のタイプ変数をパラメータまたは戻り値として使用するプレースホルダを有します.たとえば、タイプjava.util.Listは、プレースホルダEによって要素のタイプが記述されるlistの汎用タイプである.このタイプにはadd()というメソッドがあり、Eタイプのパラメータがあると宣言され、get()メソッドがあり、戻り値がEタイプと宣言されます.汎用クラスは参照タイプであり,スタックオブジェクトであり,主にタイプパラメータという概念を導入した.なぜ汎用を使用するのか汎用がなければ、集合クラスの使用には、各集合の要素のタイプを覚えておく必要があります.java 1で4種類のコレクションが作成され、コレクションに入れるオブジェクトのタイプがわかりますが、コンパイラは知りません.したがって、追加するオブジェクトタイプが必要なタイプであることを確認し、コレクションから要素を取得する必要がある場合は、オブジェクトから実際のタイプに変換するために明示的な書き込み強制タイプ変換が必要です.このような問題は、リストにStringが必要ですが、addのときに他のタイプのオブジェクトを入れると、get()のときに強制タイプ変換(String)がClassCastExceptionを放出し、このような問題も実行時にしか発見されません.Java 5.0に導入された汎用タイプはこの問題をよく解決し、リストを宣言したり、ArrayListのインスタンスを作成したりするときは、汎用タイプの名前の後ろに「<>」のペアを付けて、必要な実際のタイプをカッコに書き込む必要があります.変数タイプを宣言すると、コンパイラはコンパイル期間中に強力なタイプチェックを提供し、プログラムのタイプセキュリティを強化することができます.以前は実行時にしか発見できなかったエラーがコンパイル時に発見されます.たとえば、Stringオブジェクトしか保持できないリストがある場合、このタイプのチェックはString[]オブジェクトの追加を阻止することができます.同様に、追加されたタイプ情報は、コンパイラが私たちのためにいくつかのタイプ変換を行うことができます.たとえば、コンパイラはListにStringオブジェクトであるget()メソッドがあることを知っています.そのため、戻り値をObjectからStringに強制的に変換する必要はありません.        Java.utilのリストや他の集合クラスは汎用で書き換えられています.前述したように、リストはlistとして再定義され、その中間の要素タイプは、Eという名前の可変プレースホルダによって記述される.Add()メソッドは、以前のObjectを置換するためにEのタイプのパラメータを所望するように再定義され、get()メソッドは、以前のObjectを置換するEを返すように再定義される.簡単に言えば、汎用型を使用するには2つのメリットがあります.1つは、タイプの安全を強化することです.二、手動変換タイプの面倒を省いた基本的な汎用用法汎用タイプを使用するためには、タイプ変数に実際のタイプを詳細に指定し、Listのようなパラメータ化タイプを形成する必要がある.例:
List<String> list = new ArrayList<String>;
 
「(String)」というタイプ変換を使用して、タイプパラメータ「」に置き換えられます.異なるのは、タイプパラメータが必要で、一度だけ宣言する必要がありますが、listはタイプ変換を必要とせずに何度も使用できます.注意、Java.utilの集合クラスの要素はオブジェクト化されている必要があります.基本的なタイプではありません.汎用的な導入はこの点を変えなかった.汎用型では基本型は使用できません.SetまたはListは、1つの方法で任意の数のパラメータを使用できるように、クラスが複数のタイプのパラメータを使用できることを明らかにすることはできません.インタフェースJavautil.Mapは一例です.1つのMapは、1つのkeyのオブジェクトから1つのvalueのオブジェクトへのマッピング関係を表す.インタフェースMapは、keyのタイプを記述するためのタイプ変数と、valueのタイプが汎用タイプを使用する複雑な詳細1を記述するための別のタイプ変数とを明らかにする.タイプパラメータを持たない汎用的な使用の結果
List l = new ArrayList();
    l.add("hello"); 
    l.add(new Integer(123));
    Object o = l.get(0);
 
タイプ変数を持たない汎用タイプは未処理タイプ(raw type)と考えられる.Javaコレクションを使用する場合、説明タイプ変数は強制的に要求されず、javaコンパイルも通過できるが、javaコンパイラはヒントNote:Testを与える.java uses unchecked or unsafe operations.     Note: Recompile with -Xlint:unchecked for details. コンパイルは、リストに追加された値が正しいタイプであることを確信できないため、add()メソッドの呼び出しに警告します.未処理のタイプを使用していることを示しています.コードがタイプ安全であることを検証することはできません.-Xlintパラメータを追加して再コンパイルすると、これらの警告が表示されます:Test.java:6: warning: [unchecked]    unchecked call to add(E) as a member of the raw type java.util.List    l.add("hello");                                                                                                                                                                                      ^  Test.java:7:warning: [unchecked]    unchecked call to add(E) as a member of the raw type  java.util.List  l.add(new Integer(123)); Java 5を使用したくない場合は、0の新しい特性は、簡単に-source 1を通過することができます.4タグでコンパイルすると、コンパイラは「文句」を言わなくなります.これらの警告は、SuppressWarnings(「unchecked」)注釈を使用して無視することもできます.これにより、コンパイル時に警告はなくなりますが、リストに異なるタイプのオブジェクトを入れることができます. 2.パラメトリックタイプのアーキテクチャパラメトリックタイプには、一般的なタイプのようなタイプのアーキテクチャがあります.このシステムは変数のタイプではなく、オブジェクトのタイプに基づいています.例:
  ArrayList<Integer> l = new ArrayList<Integer>();
    List<Integer> m = l;                            // okay
    Collection<Integer> n = l;                      // okay
    ArrayList<Number> o = l;                        // error
    Collection<Object> p = (Collection<Object>)l;   // error, even with cast

我々が見たように、このXがYに変換されても、1つのListが1つのListに変換されることは許されない.しかし、1つのListを1つのListに変換することができ、このようなことを継承する方法で行うことができる.汎用型はコンパイル期間のタイプセキュリティのみを提供します.Java 5を使用する場合.0のコンパイラはコードをコンパイルし、警告がなければ、このようなコードは実行期間中もタイプが安全です.逆に、コンパイラが警告したり、未処理のタイプのようにセットのコードを変更したりした場合は、実行期間のタイプのセキュリティを確保するためにいくつかのステップを追加する必要があります.javaを使用します.util.CollectionsのcheckedList()とcheckedMap()メソッドでこれを行います.これらの方法は、集合をwrapper集合にパッケージ化し、実行時に正しいタイプの値のみが集合体に配置できることを確認します.次の例は、タイプのセキュリティ・ホールを補完できる例です.
List<Integer> li = new ArrayList<Integer>();
// Wrap it for runtime type safety
List<Integer> cli = Collections.checkedList(li, Integer.class);
// Now widen the checked list to the raw type
List l = cli;  
// This line compiles but fails at runtime with a ClassCastException.
// The exception occurs exactly where the bug is, rather than far away
l.add("hello");

 
 3.なぜパラメトリックタイプの配列がタイプ安全ではないのか汎用タイプを使用する場合、配列は特に考慮する必要があります.TがSの親(またはインタフェース)である場合、タイプはSの配列S[]であり、タイプTの配列T[]でもある.そのため、Java解釈器は、オブジェクトが配列に格納されるたびに、格納するオブジェクトタイプと格納する配列が許可するタイプが一致することを確認する必要があります.たとえば、次のコードは実行中にチェックに失敗し、ArrayStoreException例外を放出します.
String[] words = new String[10];
Object[] objs = words;
objs[0] = 1;  // 1 autoboxed to an Integer, throws ArrayStoreException
 
コンパイル時objはObject[]ですが、実行時にはString[]であり、Integerを格納するために使用できません.汎用タイプを使用する場合、1つの実行時に行われるチェックではコンパイル時のタイプパラメータ情報を取得できないため、実行時の配列に依存して異常チェックを格納するだけでは十分ではありません.次のコードを表示します.
List<String>[] wordlists = new ArrayList<String>[10];
ArrayList<Integer> ali = new ArrayList<Integer>();
ali.add(123);
Object[] objs = wordlists;
objs[0] = ali;                       // No ArrayStoreException
String s = wordlists[0].get(0);      // ClassCastException!
 
上記のコードが許可されている場合、実行時の配列格納チェックは成功します.コンパイル時のタイプパラメータがなく、コードは単純にArrayListからArrayList[]配列まで格納され、非常に正確です.コンパイラがこの方法でタイプセキュリティに勝つことを阻止できない以上、パラメトリックタイプの配列を作成することを阻止します.したがって、上記のシナリオは永遠に発生せず、コンパイラは最初の行でコンパイルを拒否し始めました.