私たちは、このような制約の一般的な集合を定義するとき、我々はまた、クラスやメソッドの柔軟性を高めることができる、汎用的なクラスやメソッドの定義に追加することができます設定することができます。継承とジェネリックを定義する際に加えて、我々はまた、ワイルドカードを追加することができます。平時の訓練では、私は(実際には、複雑ではありませんが、あまり一般的ではない)いくつかの初心者の複雑なジェネリック医薬品を発見した混乱します。ここでは例数によるプロジェクトにおけるジェネリック医薬品の一般的な使用のディスプレイに。
図1は、一般的なクラスとインタフェースに作用することができます
ようなプロジェクトのようなクラスの場合の一般的な役割、我々は倉庫に保管されもののリストで表現され、倉庫クラス(倉庫)を定義する必要があります。ウェアハウス・クラスを定義するとき、私たちはジェネリックで収容することができるデータ型のリストを指定することができます。たとえば、次のGenericClass.javaを参照してください。
1つの//インポート省略パケットコードセット あなたは、クラスを定義する際に、直接一般的なTと結合していること2 //注意 3クラス倉庫<T> { 4プライベートリスト<T> productList; //ここにノートでは、一般的なT、3行目と一致しています 5公共リスト<T> getProductList() 6 {productListを返します。} 7ます。public void setProductList(リスト<T> productList) 8 {this.productList = productList;} 9 //コンストラクタ 10公共倉庫() 11 {productList =新規のArrayList <T>();} 12は//パラメータの型がTであることを要素、してくださいメモを追加します 13ボイドのaddItem(Tアイテム) 14 {productList.add(アイテム)} 15は//すべてのオブジェクトを印刷します 16パブリックボイドprintAllItems(){ 17 // Tは、イテレータに作用します 18イテレータ<T>がproductList.iterator()=。 19一方(it.hasNext()) 20 {のSystem.out.println(it.next()のtoString());} 21} 22}
第三行はWareHourseこのクラスを定義したとき、我々はTジェネリック制約を追加し、このクラスのプロパティとメソッドは、我々は、この多くの汎用T.を使用します たとえば、T、行13の要素を追加する方法を介して一般的な制約を含むリストを作成するに4行目では、パラメータはTであり、すべてのオブジェクトを印刷するライン16にprintAllItems方法、我々ライン18にあなたはイテレータを作成し、また、使用ジェネリックT.
我々はまた、T Eと他の文字に変更することができますが、その後、使用中、Tとして定義されたら、それが必要であり、文字「T」のマッチ。
23クラスアイテム{ 商品の24 // 25プライベート文字列itemNameに。 26 //コンストラクタ 27公共の項目(文字列名) 28 {this.itemName =名;} プロパティの29の// getメソッド 30パブリックストリングgetItemName() 31 {itemNameにを返します。} 32プロパティの// setメソッド 33ます。public void setItemName(文字列itemNameに) 34 {this.itemName = itemNameに。} 35の//オーバーライドのtoStringメソッド 36公共の文字列のtoString() 37 {this.itemNameを返します。} 38}
我々は、次に、ライン25は、我々はitemNameにすることによって、このプロパティを貨物の名前を定義する第1行で商品アイテムのカテゴリ23-38を記述するために使用される倉庫を定義します。
39パブリッククラスGenericClass { 40パブリック静的無効メイン(文字列[] args){ ここでは、一般的な種で渡される41 //文字列であります 42倉庫の<string> WH =新たな倉庫の<string>(); 43 wh.addItem(の "Java")。 44 wh.addItem( "C#の")。 45 wh.printAllItems(); //出力することができるJavaやC# 46 //次は、私たちは、2つのオブジェクト項目を作成します 47項目bookItemは、新たな項目( "ブック")=; 48項目carItemは、新たな項目(「車」)を=。 ここ49 //ジェネリック種項目です 50倉庫の<item> itemWh =新たな倉庫の<item>(); 51 itemWh.addItem(bookItem)。 52 itemWh.addItem(carItem)。 53 itemWh.printAllItems(); //出力とブックカーです 54} 55}
私たちは、主な機能にはジェネリックでこの倉庫クラスを使用します。42行では、我々は一般的なタイプは、このクラスの倉庫では、Stringオブジェクト、「T」は、文字列の代わりに使用することができますと、すべての場所で指定WHオブジェクトをインスタンス化します。例えば、プライベートリスト<T> productListは、プライベートリストの<string> productListように置換されていてもよいです。44およびライン43の後に、我々は、オブジェクト、及びprintAllItems法により線45にWHに格納されているすべての商品の出力を追加するために、AddItemメソッドを呼び出します。
行50で、私たちはジェネリック型を指定すると、カスタムアイテムであり、その場合、とき52およびライン51を使用して、タイプ項目で必要なパラメータを渡し、AddItemメソッドを呼び出します。
この例では、ジェネリッククラスに作用します。そこで、我々は、このクラスでも比較的高い汎用性を持っているので、データ型のクラスを定義するために、より柔軟な方法を使用することができます。
また、汎用のインターフェイスに適用することができ、文法と効果はクラスに似ている、それが例示されていません。
また、上記のコードでは、我々はまた、このようなクラスの一般的な戻り値の型を作るために私たちの役割としての基本的な方法、上の命令にジェネリック医薬品の役割を見ました。コードは以下の通りであります:
公共リスト<T> getProductList()
また、次のように方法に作用するジェネリック型パラメータを許可します。
空のaddItem(Tアイテム)
2継承とジェネリック医薬品のワイルドカード
あなたがジェネリックを定義するとき、我々は、拡張して、汎用タイプの上限を定義することができ、また、スーパーの下限値によって定義することができる、これら二つの言葉は、通常は限られており、?キーワードを使用してのように。
たとえば、コードリストを持っているが、DEST、ここでは、手段「上記の」スーパーあって、それがスーパー父DESTオブジェクトは「父のサブクラス」に格納されなければならないことを意味し、<スーパー父?> ;?言い換えれば、どこDEST、これは、任意のサブクラスは、オブジェクトクラスの父で保存することができます。
使用方法の2で見てみましょうを拡張します。<?父を拡張>たとえば、そのようなコードがあると、リストsrcは、オブジェクトが「父」は、親クラスに格納することができる示し継承、SRCまで延び、すなわち、SRCは、オブジェクトの父の任意のサブクラスに格納することができます。
実際のプロジェクトでは、我々は一般的に一覧から一覧からリード要素のこのタイプではSRCコレクション<?父を拡張> <?スーパー父は> destが要素の、このようなコレクションを書き込みます。以下GenericExtends.javaの例では、我々は理解して来て、スーパーや?使用法を拡張します。
1つのインポートjava.util.ArrayListの。 2インポートjava.util.Listに。 3 //親クラスとサブクラスの空きスペースを定義します 4クラスの父{} 5クラスの息子は} {父を拡張します 6 //これは、メインクラス記載の主な方法であります 7パブリッククラスGenericExtends { 8 //このメソッドは、オブジェクトは、destにするSRCにコピーされます 9静的な無効コピー(一覧<?スーパー父> DEST、 10リスト<?父> SRC)は{延び 11のために(INTがI = 0、I <src.size(); I ++) 12 {dest.add(src.get(I))。} 13}
9行コピー方法上の2つのパラメータでは、我々は、2つのパラメータを拡張し、スーパージェネリック含まれて参照してください。ループ方式のためのボディでは、我々のアプローチは、今述べた原則と一致している:収集ベルトからの読み出しは、書面で持参しジェネリック医薬品、スーパージェネリックコレクションに延びています。
14パブリック静的無効メイン(文字列[] args){ 15父F =新しい父()。 16ソンS =新しい子(); 17 //父とジェネリックコレクションを作成し、どの要素を入れて 18リスト<父> srcFatherList =新しいのArrayList <父>(); 19 srcFatherList.add(F)。 20リスト<父> destFatherList =新しいのArrayList <父>(); 21は、//コピー方法により、destFatherList内に要素をコピー 22コピー(destFatherList、srcFatherList)。 ここ23 //出力が正常destFatherListに要素を書き込むための方法をコピー示し、1であります 24のSystem.out.println(destFatherList.size())。 25} 26}
パラメータの定義方法は、我々が使用できる場合にはベルトが延びており、入力パラメータのスーパージェネリック型は、精度を確保します。また、両方の一般的な少しの使用は、例えば、主な機能、あなたが呼び出すコピー方法の最初の22行では、我々は、パラメータが一覧<父>タイプです渡します。
のは、いくつかの間違った使用方法をお見せしましょう:
使用法エラー:インスタンス化されたコレクションオブジェクトと疑問符の付いたタイプ。
1リスト一覧=新しいのArrayList <文字列>()<?>; //正确
2 //リスト一覧=新しいArrayListを()<?> <?>; //错误
等号の左側には、署名が1行目は、我々は疑問符を使用しますが、右側に、我々はこれが正しいと、ジェネリック型はStringで確立しました。コンパイラは、一般的なタイプのセットが使用されたリストを知らないのでこれとは対照的に、左と右の私たちは疑問符を使用等号のは、これは、間違っています。
WRONG 2:<?父を拡張>書き込みにジェネリックコレクションを含めます。
1リスト<?父が伸びる>リスト=新しいのArrayList <父>();
2 //list.add(f)。//エラー
コンパイラは、正確にサブタイプ父が何であるかについて知らないので、2行目には、構文エラーを報告します。決定していないので、型の安全性を確保するために、我々は追加データがそれを埋めることはできませんので。"
WRONG 3:コレクションは一般的な読み取りが含まれているから<スーパー父?>。
1リスト<?スーパー父>リスト1 =新しいのArrayList <父>();
2 list.add(F); //正しいです
3 //list.get(0);//エラー
コンパイラは父の親が慣れるの戻り値を受け取るために何を知っていないため、3行目では、構文エラーを報告しますので、同じタイプの私たちが読むことを許可されていないので、安全性を確保するために。
上記の使用の第二及び第三の誤差から、我々は、感じる延び、スーパー両方外部メソッドパラメータを定義することに加えて、一般的な使用法を定義することができ、それは実際には他の適切な用途ではありません。