Java の汎用メソッドの使用方法

王林
リリース: 2023-05-01 14:16:06
転載
2602 人が閲覧しました

ジェネリック メソッド

は通常、次のように定義されます。つまり、

public class FTest {
	public <t> List<t> f(T t){...};
}</t></t>
ログイン後にコピー

がメソッドの前に追加されます。3 つのジェネリック パラメーター推論メソッド:

1. 決定されたジェネリック型

fTest.<integer>f(xxx)</integer>
ログイン後にコピー

2 を f() の前に直接追加し、入力パラメーターを通じて決定します。次の推論は Integer

int number = 0;
fTest.f(number)
ログイン後にコピー

3 です。渡されました 戻り値 OK

List<integer> list = fTest.f(xxx);</integer>
ログイン後にコピー

Q: 次のコードのどこが間違っていますか? toString() はありますか?

public class A<t> {
	public static void  test(T t){
  		System.out.println(t.toString());  
  }
}</t>
ログイン後にコピー

A: テストは静的メソッドであるため、A インスタンスの T
は検出できないため、
public static void test(T t)

toString() toString は Object のメソッドなので問題ありません。

汎用パラメータと型の削除

Q: 汎用パラメータ T は実行時にどうなりますか?
A: オブジェクトに統合されており、型情報は含まれません。

Q:instanceof はジェネリック パラメーター T の比較に使用できますか?

class A<t> {
   void f(Object arg)
   if(arg instanceof T) {
	  ...
   }
}</t>
ログイン後にコピー

A: いいえ、コンパイラはエラーを報告します。

Q: new T() または new T[] 操作は汎用パラメーター T に対して実行できますか?
A: いいえ、コンパイラーはエラーを報告します。

Java の汎用メソッドの使用方法

#Q: ジェネリック パラメーター オブジェクトのメソッドを呼び出すことはできますか?

T.f();
ログイン後にコピー

A: オブジェクトのメソッドのみを呼び出すことができます。

Q: T は強制変換に使用できますか?

T t = (T)object;
ログイン後にコピー

A: 実行できますが、実際には変換は行われず、コンパイル中に警告がトリガーされます。

新しい汎用オブジェクトを作成するときの質問

基本クラス Parent とサブクラス Child の 2 つのクラスがあると仮定します。

class Parent{}
class Child extends Parent{}
ログイン後にコピー

次の質問に答えてください:
Q : 以下 この文に何か問題がありますか?

List<parent> list = new ArrayList<child>()</child></parent>
ログイン後にコピー

A: 問題があります。コンパイルが間違っています。 List と ArrayList

#Q:

List extends Parent> list = new ArrayList<child>();</child>
ログイン後にコピー
このリストの特徴は何ですか?

A: このリストは A a = list.get() を呼び出すことができますが、list.add(new Parent()) はできません。

  • 理由:

    list .get() が行うことは、戻るときに内部の extend Parent> を Parent に強制変換することです。これは合理的です。Parent のサブクラスは Parent
    list.add(new Parent ()) に変換できます。入力中に外部 A を内部 extend Parent> に変換します。この Parent オブジェクトがどの Parent サブクラスに変換できるかわからないため、これは不合理です。

Q:

List super Child> list = new ArrayList<parent>();</parent>
ログイン後にコピー
このリストの特徴は何ですか?

誰が以下のエラーを報告しますか

list.add(new Child())
list.add(new Parent())
Parent a= list.get();
Child b = list.get()
ログイン後にコピー
A: スクリーンショットは次のとおりです:

Java の汎用メソッドの使用方法

    ##Child c = list.get () または Parent p = list.get() によって行われる操作は、戻るときに内部の super Child> を外部の Parent または Child> に強制することですが、コンパイラは子の親クラス
  • を考慮しているため、これは不合理です。

    必ずしもそうとは限りません は親または子に変換できるため、この動作は禁止されています (たとえば、親の親クラスはオブジェクトですが、オブジェクトは親または子に変換できない場合があります)。 *list.add(new Child()) によって行われる操作は、入力中に外部の子または親を内部の super Child> に変換することです。子と親は確実に子に変換できるため、これは合理的です。親クラス。

  • Q:
List> list = new ArrayList<a>();</a>
ログイン後にコピー

このリストの特徴は何ですか?

A: get も add も使用できず、戻り値なし、入力 A なしの削除などの操作のみ実行できます。

PS: get メソッドまたは add メソッドを呼び出すことができないという意味ではなく、get または add メソッドを呼び出すときにオブジェクト A を使用して操作できないことに注意してください。

つまり、add(A) または A a = get(0) は実行できません。
しかし、add(object) または Object o = get(0) は実行できます。
なぜなら? Object には変換できますが、A には変換できません。

Q: 次のコードはエラーを報告しますか?

   List<fruit> fruitList = new ArrayList();
   fruitList.add(new Fruit());
   List<apple> appleList = new ArrayList();
   appleList.add(new Apple());
   fruitList.addAll(appleList);
   System.out.println(fruitList);</apple></fruit>
ログイン後にコピー

A: エラーは報告されません。結果は正常に出力されます。

Java の汎用メソッドの使用方法PECS原則

PECS原則と上記の違いに注目してください!

上記の ? extend または ? supert はどちらもオブジェクトを宣言するときに使用されます。
PECS 原則は、汎用オブジェクトのメソッド入力パラメーターに使用されます。

次のように定義されたクラスがあるとします。

public static class MyList<t> {
    List<t> list = new ArrayList();

    // 把输入参数塞给自己,类似于生产操作
    public void pushList(List<t> t) {
        list.addAll(t);
    }

    // 把自己的内容塞给输入参数,类似于让输入参数做消费。
    public void pollList(List<t> t) {
         t.addAll(list);
    }
}</t></t></t></t>
ログイン後にコピー

T は汎用パラメーターです。

Q: 次のコードは正常に実行できますか?

MyList<number> myList = new MyList();

List<integer> intList = new ArrayList();
myList.pushList(intList);

List<object> objectList = new ArrayList();
myList.pollList(objectList);</object></integer></number>
ログイン後にコピー

A: 正常に実行できません。pushList と pollList の両方がエラーを報告します。

チェックした後、コンパイラは List と List が同じものではないと判断するためです。

Q: 上記の PushList をサポートしたい場合、pushList メソッドの定義をどのように変更すればよいですか?

A: これを次のように変更します:

// 把输入参数塞给自己,类似于生产操作
public void pushList(List extends T> t) {
    list.addAll(t);
}
ログイン後にコピー

つまり、コンパイラは List と List が同じものであるとみなします、許可されます!

Q: pollList をサポートしたい場合、定義を変更するにはどうすればよいでしょうか?

A:

// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List super T> t) {
    t.addAll(list);
}
ログイン後にコピー

因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List 和List super Number>是一个东西,允许!

PECS原则出自Effective Java, 注意只是一个编程建议而已!

  • 如果有一个类A,泛型参数为T

  • 如果他一般只用于接收输入容器List后,塞入自己内部的T容器, 则类A就叫生产者, 因此输入参数最好定义为 extend T>最好, 以便能接收任何T子类的容器。

  • 如果他一般只用于接收输入容器后List, 把自己内部的T元素塞给它, 那么这个类A就叫消费者, 输入参数最好定义为 super T>\ 最好, 以便自己的T元素能塞给任何T元素的父类容器。

以上がJava の汎用メソッドの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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