ホームページ  >  記事  >  Java  >  Java ジェネリックスとラッパー クラスのサンプル分析

Java ジェネリックスとラッパー クラスのサンプル分析

王林
王林転載
2023-04-21 19:19:06757ブラウズ

1. ジェネリックスとは何ですか?

ジェネリックスの本質は、型をパラメーター化することです (新しい型を作成せず、ジェネリックスで指定されたさまざまな型を通じてパラメーター制限の特定の型を制御します)。

まず次の例を見てみましょう:

前に学習した配列は、指定された型の要素のみを格納できます。例: 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 サブスクリプト 元々は文字列ですが、ジェネリックスを導入するには

と強制的に入力する必要があります。ジェネリックスの目的は、現在のコンテナが保持するオブジェクトのタイプを指定し、コンパイラ 自分で調べてください。

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;
        }
    }
  • 消去メカニズム: a8093152e673feb7aba1828c43532094 内の型はコンパイル中に消去されるため、 a8093152e673feb7aba1828c43532094 内のは型の構成には関与しません。 T をオブジェクトとして消去します。

ジェネリック型の配列をインスタンス化できないのはなぜですか?

配列とジェネリックの重要な違いは、型チェックを強制する方法です。配列は実行時に型情報を保存してチェックしますが、ジェネリックはコンパイル時に型エラーをチェックします。

返された Object 配列には、int 型の配列を通じて受信した文字列などの任意の型のデータが格納される可能性があります。コンパイラはそれを安全でないとみなします。

3. ジェネリックの上限

構文:

class ジェネリック クラス名520c25779a67ecd8a9988f6989348733{

}

例:

public class MyArray{} //E は Number または Number のサブクラスのみです。

public class MyArray091a568f4b5c8ae6ac2165c84c2d6226>{}

//E は Comparable インターフェイスを実装するクラスである必要があります

[注] 境界を指定しない E の場合、 E extends Object

4、ワイルドカード文字

#? が表示されます。ジェネリックで使用する場合、これはワイルドカードです。ワイルドカードは、アンチジェネリック型が共変できないという問題を解決するために使用されます。

次の 2 つのコード:

代码一:
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) ワイルドカード文字の上限

構文:

b6b24cff7aea61f4b9dfa82bc05f59f5

a2b037db85f4e1df0e812b9647ac55a8 //渡すことができる実際のパラメータの型は、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:

//親と子の型を決定するにはワイルドカードを使用する必要があります

MyArrayLista2b037db85f4e1df0e812b9647ac55a8 は MyArrayListc0f559cc8d56b43654fcbe4aa9df7b4a または MyArrayListec962f3901233a4fea9ed3b7ba4d8a09 は MyArrayList< ;? は Number> の親クラスを拡張します

 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) ワイルドカードの下限

  • 構文:

f7f07e6da1289ee684d889de53a57ca3

< ; ? super Integer>//渡せるパラメータの型は Integer または Integer の親クラスです

ワイルドカード下限の親子クラス関係:

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 サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。