ジェネリックスの本質は、型をパラメーター化することです (新しい型を作成せず、ジェネリックスで指定されたさまざまな型を通じてパラメーター制限の特定の型を制御します)。
まず次の例を見てみましょう:
前に学習した配列は、指定された型の要素のみを格納できます。例: int[] array=new int[10];String[] array=new String[10];
Object クラスはすべてのクラスの親クラスなので、Obj 配列を作成できますか?
class Myarray{ public Object[] array=new Object[10]; public void setVal(int pos,Object val){ this.array[pos]=val; } public Object getPos(int pos){ return this.array[pos]; } } public class TestDemo{ public static void main(String[] args) { Myarray myarray=new Myarray(); myarray.setVal(1,0); myarray.setVal(2,"shduie");//字符串也可以存放 String ret=(String)myarray.getPos(2);//虽然我们知道它是字符串类型,但是还是要强制类型转换 System.out.println(ret); } }
上記のコードを実装すると、次のことがわかりました。
あらゆる種類のデータを保存できる
いいえ。 2 サブスクリプト 元々は文字列ですが、ジェネリックスを導入するには
と強制的に入力する必要があります。ジェネリックスの目的は、現在のコンテナが保持するオブジェクトのタイプを指定し、コンパイラ 自分で調べてください。
class 汎用クラス名02eecac03861c3fe32368f099694b87f{
//型パラメータはここで使用できます
}
ジェネリックスの使用:
ジェネリック クラス3cafac1a5b1a5a24a9212c4d79413436 変数名=new ジェネリック クラス3cafac1a5b1a5a24a9212c4d79413436(コンストラクタ メソッドの実パラメータ)
##MyArray list=new MyArraya8093152e673feb7aba1828c43532094();#[注]
## の後の a8093152e673feb7aba1828c43532094 type はプレースホルダーを表し、現在のクラスがジェネリック クラスであることを示します
##ジェネリックをインスタンス化する場合、a8093152e673feb7aba1828c43532094 はできません。これは単純な型であり、ラッパー クラスである必要があります
a8093152e673feb7aba1828c43532094ジェネリックに参加しない型合成
新しいジェネリック型 Array
はできませんジェネリックスの使用にはキャスト型の変換は必要ありません
単純なジェネリック:
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 //在实例化泛型类时,必须指定T的具体类型 public class Test<T>{ //key这个成员变量的类型为T,T的类型由外部指定 private T key; public Test(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定 this.key = key; } public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 return key; } }
ジェネリック型の配列をインスタンス化できないのはなぜですか?
配列とジェネリックの重要な違いは、型チェックを強制する方法です。配列は実行時に型情報を保存してチェックしますが、ジェネリックはコンパイル時に型エラーをチェックします。
返された Object 配列には、int 型の配列を通じて受信した文字列などの任意の型のデータが格納される可能性があります。コンパイラはそれを安全でないとみなします。
3. ジェネリックの上限
構文: class ジェネリック クラス名520c25779a67ecd8a9988f6989348733{public class MyArray{} //E は Number または Number のサブクラスのみです。}
例:
//E は Comparable インターフェイスを実装するクラスである必要がありますpublic class MyArray091a568f4b5c8ae6ac2165c84c2d6226>{}
[注] 境界を指定しない E の場合、 E extends Object4、ワイルドカード文字
#? が表示されます。ジェネリックで使用する場合、これはワイルドカードです。ワイルドカードは、アンチジェネリック型が共変できないという問題を解決するために使用されます。
代码一: public static<T> void printList1(ArrayList<T> list){ for(T x:list){ System.out.println(x); } } 代码二: public static<T> void printList2(ArrayList<?> list){ for(Object x:list){ System.out.println(x); } }
コード 2 ではワイルドカードが使用されています。コード 1 と比較すると、現時点ではコード 1 に渡される特定のデータ型については明確ではありません。
(1) ワイルドカード文字の上限
構文:
b6b24cff7aea61f4b9dfa82bc05f59f5a2b037db85f4e1df0e812b9647ac55a8 //渡すことができる実際のパラメータの型は、Number または Number のサブクラスです。例: 次のリレーションシップの場合、Animal または Animal のサブクラスを格納するリストを出力するメソッドを記述する必要があります。 。Animal
Cat は Animal を拡張
Dog は Animal を拡張
コード 1:public static <t extends Animal> void print1(List<T> list>{ for(T animal:list){ System.out.println(animal);//调用了T的toString } }現時点では、T 型はサブクラスです動物のことも、あなた自身のことも。
コード 2: ワイルドカードを使用して実装
public static void print2(List<? extends Animal> list){ for(Animal animal:list){ Syatem.out.println(animal);//调用了子类的toString方法 } }
2 つのコードの違い:
#ジェネリックによって実装されたメソッドの場合、370684dcd157e96b03c92635015a5aca は次のことを課しますAnimal のサブクラスにのみなれる T に対する制限。キャットを通り越して、キャットです。
ワイルドカードによって実装されたメソッドの場合、Animal を規定し、Animal のサブクラスを渡すことを許可することと同じです。現時点では、具体的なサブカテゴリは明らかではありません。例: Cat が渡されるとき、宣言された型は実際には Animal です。ポリモーフィズムを使用することによってのみ、Cat の toString メソッドを呼び出すことができます。
ワイルドカードの上限→親子クラスrelationship:
ArrayList<Integer> arrayList1 = new ArrayList<>(); ArrayList<Double> arrayList2 = new ArrayList<>(); List<? extends Number> list = arrayList1; //list.add(1,1);//报错,此时list的引用的子类对象有很多,再添加的时候,任何子类型都可以,为了安全,java不让这样进行添加操作。 Number a = list.get(0);//可以通过 Integer i = list.get(0);//编译错误,只能确定是Number子类[注]
はできませんリストに格納されるのは、型が判別できない Number または Number A のサブクラスである可能性があります。
ワイルドカードの上限は読み取りには適していますが、書き込みには適していません。
(2) ワイルドカードの下限
ワイルドカード下限の親子クラス関係:MyArrayList474555482eb79f9e4e676a9012437c1d是MyArrayList1c0477c859e3a4cbd4faa63087d62a35的父类类型
MyArrayLista10469e4b40f04339ce5bebfbf5abb4c是MyArrayList474555482eb79f9e4e676a9012437c1d的父类
通配符下界适合写入元素,不适合读取。
5、包装类
在Java中,由于基本类型不是继承自Object,为了在泛型中可以支持基本类型,每个基本类型都对应了一个包装类。除了Integer和Character,其余基本类型的包装类都是首字母大写。
拆箱和装箱:
int i=10; //装箱操作,新建一个Integer类型对象,将i的值放入对象的某个属性中 Integer ii=i; //自动装箱 //Integer ii=Integer.valueOf(i); Integer ij= new Integer(i);//显示装箱 //拆箱操作,将Integer对象中的值取出,放到一个基本数据类型中 int j=ii.intValue();//显示的拆箱 int jj=ii;//隐式的拆箱
以上がJava ジェネリックスとラッパー クラスのサンプル分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。