は通常、次のように定義されます。つまり、
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
は検出できないため、
public static
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: いいえ、コンパイラーはエラーを報告します。
#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
List extends Parent> list = new ArrayList<child>();</child>
list .get() が行うことは、戻るときに内部の extend Parent> を Parent に強制変換することです。これは合理的です。Parent のサブクラスは Parent
list.add(new Parent ()) に変換できます。入力中に外部 A を内部 extend Parent> に変換します。この Parent オブジェクトがどの Parent サブクラスに変換できるかわからないため、これは不合理です。
List super Child> list = new ArrayList<parent>();</parent>
誰が以下のエラーを報告しますか
list.add(new Child()) list.add(new Parent()) Parent a= list.get(); Child b = list.get()
必ずしもそうとは限りません は親または子に変換できるため、この動作は禁止されています (たとえば、親の親クラスはオブジェクトですが、オブジェクトは親または子に変換できない場合があります)。 *list.add(new Child()) によって行われる操作は、入力中に外部の子または親を内部の super Child> に変換することです。子と親は確実に子に変換できるため、これは合理的です。親クラス。
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: エラーは報告されません。結果は正常に出力されます。
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
Q: 上記の PushList をサポートしたい場合、pushList メソッドの定義をどのように変更すればよいですか?
A: これを次のように変更します:// 把输入参数塞给自己,类似于生产操作 public void pushList(List extends T> t) { list.addAll(t); }
Q: pollList をサポートしたい場合、定義を変更するにはどうすればよいでしょうか?
A:// 把自己的内容塞给输入参数,类似于让输入参数做消费。 public void pollList(List super T> t) { t.addAll(list); }
因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List
PECS原则出自Effective Java, 注意只是一个编程建议而已!
如果有一个类A,泛型参数为T
如果他一般只用于接收输入容器List后,塞入自己内部的T容器, 则类A就叫生产者, 因此输入参数最好定义为 extend T>最好, 以便能接收任何T子类的容器。
如果他一般只用于接收输入容器后List, 把自己内部的T元素塞给它, 那么这个类A就叫消费者, 输入参数最好定义为 super T>\ 最好, 以便自己的T元素能塞给任何T元素的父类容器。
以上がJava の汎用メソッドの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。