Java の extends T と super T とは何ですか?

PHPz
リリース: 2023-05-09 11:19:17
転載
1317 人が閲覧しました

? ワイルドカード型

  • ## は型の上限を示し、パラメーター化された型が T または T のサブクラスである可能性があることを示します;

  • は型の下限 (Java Core ではスーパー型修飾と呼ばれます) を表し、パラメータ化された型がこの型のスーパー型 (親型) であることを Object まで示します。

上限
import java.util.LinkedList;
import java.util.List;

public class test {
    public static void main(String[] args) {
        List<? extends Father> list = new LinkedList<>();
        list.add(new Son());
    }
}
class Human{
}
class Father extends Human{
}
class Son extends Father{
}
class LeiFeng extends Father {
}
ログイン後にコピー
list.add(new Son()); この行はエラーを報告します: メソッド put(Son) はタイプ List

に対して未定義です

List は、「Son から継承された任意の型を持つリスト」を意味し、コンパイラは List が保持する型を判断できないため、リストにオブジェクトを安全に追加できません。 null は任意の型を表すことができるため、null を追加できます。したがって、List の add メソッドは意味のある要素を追加できませんが、既存のサブタイプ List の割り当ては受け入れることができます。

これを実行してみてください:

List<? extends Father> list = new LinkedList<Son>();
list.add(new Son());
ログイン後にコピー

Son 型を指定した場合でも、add メソッドを使用して Son オブジェクトを追加することはできません。 Father クラスと Father クラスのサブクラスを

リストに追加できないのはなぜですか? それを分析してみましょう。

List は、上限が Father であり、次の代入が正当であることを意味します

   List<? extends Father> list1 = new ArrayList<Father>();
   List<? extends Father> list2 = new ArrayList<Son>();
   List<? extends Father> list3 = new ArrayList<LeiFeng>();
ログイン後にコピー

If List は、add メソッドをサポートします:

list1 は Father と Father のすべてのサブクラスを追加できます;
  • list2 は Son と Son のすべてのサブクラスを追加できます;
  • list3 は LeiFeng とすべての LeiFeng サブクラスを追加できます。
  • 次のコードはコンパイルに合格しません:
  • list1.add(new Father());//error
    list1.add(new Son());//error
    ログイン後にコピー
その理由は、コンパイラーはコンテナーがファーザーまたはその派生クラスであることのみを認識しており、認識していないためです。特定のタイプ。もしかして父さん?もしかして息子さん?もしかしたらレイフェン、シャオミン?後で代入に Father が使用されることをコンパイラーが認識すると、コレクション内のパラメーターの型は「Father」に限定されなくなります。代わりに、プレースホルダーでマークされています: CAP#1 は、ファーザーまたはファーザーのサブクラスをキャプチャしていることを示します。特定のクラスはわかりませんが、コードは CAP#1 です。次に、Son、LeiFeng、または Father コンパイラを挿入するかどうかは、この CAP#1 に一致するかどうかわからないため、許可されません。

ワイルドカード と型パラメーターの違いは、コンパイラーにとって、すべての T が同じ型を表すことです。たとえば、次の汎用メソッドでは、3 つの T はすべて同じ型 (String または Integer) を参照しています。

public <T> List<T> fill(T... t);
ログイン後にコピー

しかし、ワイルドカード にはそのような制約はありません。List は単に、コレクション内に何かがあるが、それが何であるかわからないことを意味します。

つまり、ここでのエラーは、List には何も入れられないということです。

List list は追加できませんが、このフォームは依然として非常に便利です。add メソッドは使用できませんが、Season は初期化中にさまざまなタイプを指定できます。例:

List<? extends Father> list1 = getFatherList();//getFatherList方法会返回一个Father的子类的list
ログイン後にコピー

さらに、親クラスまたはそのサブクラスの 1 つが List に格納されていることを確認したため、get メソッドを使用して値を直接取得できます:

List<? extends Father> list1 = new ArrayList<>();
Father father = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Object object = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Human human = list1.get(0);//读取出来的东西只能存放在Father或它的基类里。
Son son = (Son)list1.get(0);
ログイン後にコピー

下限< ;? super T> は格納には影響しませんが、取得は Object オブジェクトにのみ配置できます。

下限は super で宣言され、パラメータ化された型が指定された型である可能性があることを示します。またはこのタイプの親タイプ (オブジェクトまで)。

//super只能添加Father和Father的子类,不能添加Father的父类,读取出来的东西只能存放在Object类里
List<? super Father> list = new ArrayList<>();
list.add(new Father());
list.add(new Human());//compile error 
list.add(new Son());
Father person1 = list.get(0);//compile error 
Son son = list.get(0);//compile error 
Object object1 = list.get(0);
ログイン後にコピー

下限は要素の最小粒度の下限を指定するため、実際にはコンテナ要素の型制御が緩和されます。この要素はFatherの基底クラスであるため、Fatherよりも小さい粒度で格納できます。型安全性の理由から、Father オブジェクトまたはそのサブクラス (Son など) を追加できますが、コンパイラは List の内容が Father のどのスーパークラスであるかを認識しないため、特定のスーパークラスを追加することはできません。 . クラス (人間など)。 Object は Java クラスの最終的な祖先クラスであるため、これを読み取ると、コンパイラはその型を認識せずに Object オブジェクトのみを返すことができます。ただし、この場合、要素の型情報はすべて失われます。

PECS 原則

最後に、PECS (Producer Extends Consumer Super) 原則とは何かを見てみましょう。これはすでによく理解されています:

# 頻繁に外部から読み込むコンテンツの場合は、上限拡張を使用するのが適しています。

  • 頻繁に入れるならネザースーパーが適しています。

以上がJava の extends T と super T とは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート