JAva汎用、汎用の基本的な紹介と使用

5062 ワード

今からjavaの汎用型を深く勉強し始めました.以前は集合の中で単純に汎用型を使っていただけで、汎用型の原理と役割が全然分かりませんでした.汎用型はjavaにおいて、非常に重要な特性であるため、よく研究しなければならない.一、汎型の基本概念汎型の定義:汎型はJDK 1.5の新しい特性である.その本質はパラメトリックタイプ(Parameterized Type)の応用であり、つまり操作されるデータ型は1つのパラメータとして指定され、使用時に特定のタイプを指定する.このパラメータタイプはクラス、インタフェースとメソッドの作成に用いることができ、それぞれ汎用クラス、汎用インタフェースと汎用メソッドと呼ぶ.汎用思想はC++言語のテンプレート(Templates)では根が生え始め、Java言語がまだ汎用化されていないバージョンにある場合、Objectがすべてのタイプの親であることとタイプ強制変換の2つの特徴の組み合わせによってのみタイプ汎用化が実現されます.たとえばハッシュテーブルのアクセスでは、JDK 1.5の前にHashMapでget()メソッドを使用し、値を返すのがObjectオブジェクトです.Java言語のすべてのタイプがjavaに継承されているためです.lang.Object,そのObjectが任意の対象成都に転換することは可能である.しかし、無限の可能性もあるため、このObjectがどのようなタイプのオブジェクトなのかを知るのはプログラマーと実行期間の仮想マシンだけです.コンパイル中、コンパイラはこのObjectの強制的な転換が成功したかどうかを検査することができず、プログラマに依存してこの操作の正確性を保障するだけで、多くのClassCastExceptionのリスクがプログラムの実行期間に転嫁されます.汎用技術のC#とJavaでの使用方法は同じように見えますが、実現には根本的な違いがあります.C#の汎用技術はプログラムのソースコードにかかわらず、コンパイル後のIL中(Intermediate Language,中間言語,このとき汎用型は1つのプレースホルダ)または実行期間のCLRには確実に存在し,ListとListは2つの異なるタイプであり,システム実行期間に生成され,独自の虚メソッドテーブルとタイプデータがあり,この実装をタイプ膨張と呼び,この方法に基づいて実現される汎用型を真の汎用型と呼ぶ.Java言語における汎用型は異なり、プログラムソースコードにのみ存在し、コンパイル後のバイトコードファイルには、元のタイプに置き換えられました(Raw Typeは、ヌードタイプとも呼ばれる)となり、対応する場所に強制変換コードが挿入されているため、実行期間のJava言語ではArrayListとArrayListは同じクラスである.したがって、汎用技術は実際にはJava言語のシンタックスであり、Java言語における汎用実現方法をタイプ消去と呼び、この方法に基づいて実現される汎用は擬似汎用と呼ばれるを選択します.汎用メカニズムを使用して作成されたプログラムコードは、Object変数を乱雑に使用した後、強制型変換を行うコードよりも安全性と可読性が優れています.汎用は集合クラスにとって特に役立ちます.汎用プログラム設定(Generic Programming)は、作成されたコードが多くの異なるタイプのオブジェクトで再利用できることを意味します.
実例分析:JDK 1.5以前、Java汎用プログラム設計は継承で実現されていた.Objectクラスは使用するクラスのベースクラスであるため、1つのObjectタイプの参照を維持するだけでよい.例えばArrayListは1つのObject参照の配列のみを維持する:public class ArrayList//JDK 1.5より前の{public Object get(int i){......}public void add(Object o){......} ...... private Object[] elementData; } これには2つの問題があります:1、エラーチェックがなく、配列リストにクラスのオブジェクトを追加することができます2、要素を取るときに強制タイプ変換を行う必要があります.これにより、エラーが発生しやすくなります.例えば:/*jdk 1.5以前の書き方では、問題が発生しやすい/ArrayList arrayList 1=new ArrayList()arrayList1.add(1); arrayList1.add(1L); arrayList1.add("asa"); int i=(Integer) arrayList1.get(1);//取り出した値のタイプが分からないので、タイプ変換時にエラーが発生しやすいここの最初の要素は長整型で、整形だと思っていたので、強転時にエラーが発生しました.
だから.JDK 1.5その後,汎用型を加えて類似の問題を解決した.例えばArrayListでは汎用:/**jdk 1を用いる.5その後、汎用*/ArrayList arrayList 2=new ArrayList();//配列リストのタイプ//arrayList 2を限定する.add(1);//タイプ限定なので整形//arrayList 2は追加できません.add(1L);//タイプを限定するため、全長arrayList 2を追加することはできない.add("asa");//文字列String str=arrayList 2しか追加できません.get(0);//取り出した値のタイプがわかるので、強制タイプ変換は不要です
汎用特性は前方互換性であることも理解される.JDK 5.0の標準クラスライブラリには、集合フレームワークなどの多くのクラスが汎用化されていますが、HashMapやArrayListなどの集合クラスを使用する既存のコードは、JDK 1.5で変更せずに作業を続けることができます.もちろん、汎用化されていない既存のコードは、汎用化されたタイプのセキュリティのメリットを得ることはできません.
汎用型を学ぶ前に、汎用型の基本的な用語を簡単に紹介します.ArrayListとArrayListで簡単に紹介します.ArrayListとなる汎用タイプArrayList全体のEをタイプ変数またはタイプパラメータと呼びます.ArrayList全体をパラメトリックタイプArrayListと呼ぶintegerをタイプパラメータと呼ぶインスタンスまたは実際のタイプパラメータ・ArrayListのtypeof Integer ArrayListを元のタイプと呼びます
二、汎用の汎用を使用するパラメータタイプは、汎用クラス、汎用インタフェース、およびメソッドの作成に使用することができ、それぞれ汎用クラス、汎用インタフェース、および汎用メソッドと呼ばれる.具体的にどのように定義されているかを見てみましょう.1、汎用クラスの定義と1つの汎用クラス(generic class)の使用は1つ以上のタイプ変数を持つクラスである.1つの汎用クラスを定義するのは非常に簡単で、クラス名の後ろに<>を付けるだけで、そこにタイプパラメータを加える:public static ArrayList empty(){return new ArrayList<>()}
public static  HashMap emptyHashMap() {
    return new HashMap<>();
}

この汎用クラスを使用できるようになりました:List>list=ListUtil.empty();
2、汎用インタフェースの定義と使用定義汎用インタフェースと汎用クラスの差は多くなく、以下の簡単な例を見てください:interface Show{void show(T t,U u);
class ShowTest implements Show{ @Override public void show(String str,Date date) { System.out.println(str); System.out.println(date); } } テスト:public static void main(String[]args)throws ClassNotFoundException{ShowTest showTest=new ShowTest();showTest.show("Hello",new Date();
3、汎用メソッドの定義と汎用クラスを使用して、複数のメソッド署名間でタイプ制約を実施する.リストには、タイプパラメータVがget()、add()、contains()などのメソッドの署名に現れる.Mapタイプの変数を作成すると、メソッド間でタイプ制約を宣言します.add()に渡される値はget()が返す値のタイプと同じになります.同様に、汎用メソッドを宣言するのは、一般的に、メソッドの複数のパラメータの間でタイプコンストレイントを宣言したいためです.簡単な例を挙げると、public static void main(String[]args)throws ClassNotFoundException{String str=get("Hello","World");System.out.println(}
public static  T get(T t, U u) {
    if (u != null)
        return t;
    else
        return null;
}

三、汎用変数のタイプは上に限定され、汎用クラス、汎用インタフェース、および汎用方法を簡単に学習した.私たちはこのような形式を直接使用して汎用型の宣言を完成します.クラス、インタフェース、またはメソッドがタイプ変数を制約する必要がある場合があります.以下の例を見ると、public static T get(T t 1,T t 2){if(t 1.compareTo(t 2)>=0);//コンパイルエラーreturn t 1;}コンパイル前、つまりこの汎用メソッドを定義していたとき、この汎用タイプTがいったいどんなタイプなのか分からなかったので、Tを元のタイプObjectとしてデフォルト化するしかありません.したがって、Objectからのいくつかのメソッドのみを呼び出すことができ、compareToメソッドを呼び出すことはできません.しかし、私の本意はt 1とt 2を比較することです.どうすればいいですか.このとき、タイプ限定を使用して、タイプ変数Tに対して限定(bound)を設定するようにします.Comparableインタフェースを実装するすべての方法には、comparareToメソッドがあることを知っています.したがって、public static T get(T t 1,T t 2){//タイプ限定if(t 1.compareTo(t 2)>=0);return t 1;}
タイプ限定は、汎用クラス、汎用インタフェース、および汎用メソッドで使用できますが、以下の点に注意してください.1、この限定がクラスであろうとインタフェースであろうと、統一的にキーワードextends 2を使用し、public static T get(T t 1,T t 2)3、既存のインタフェースでもクラスでもある場合、クラスは1つのみでなければなりません.そして、先頭位置public static T get(T t 1,T t 2)