2

私はJAVAジェネリックの概念でいくつかの小さな実践をテストしています。

汎用の関数からリストを返そうとしましたが、コンパイルでは返されません。

以下のコードを確認してください:

package com.test.generic.method;

import java.util.ArrayList;
import java.util.List;


public class Sample_3<T> {

    public <T> List<T> testReturn(T t) {
        List<T> list = new ArrayList<T> ();
        list.add(t);
        return list;
    }

    public static void main(String a[]) {
        String s = "Gunjan";

        Sample_3 sample = new Sample_3<String>();
        List<String> list =(List<String>) sample.testReturn(sample);


        for(String ab : list){
            System.out.println(ab);
        }

    }
}

それは与えるClassCastException

ジェネリック関数からリストを返すにはどうすればよいですか?そして、なぜJAVAはそのようなコンパイル時機能を追加したのですか?

ありがとう、グンジャン。

4

5 に答える 5

5

Theジェネリックの目的は、自由に指定できるようにすることです。したがって、次のようなことができます:

public List<T> testReturn(T t){
        List<T> list = new ArrayList<T>();
        list.add(t); 
        return list; 
    }

これにより、たとえば次のことが可能になります

List<String> a = testReturn("A");
List<Integer> b = testReturn(1);

コードの問題は、メソッドの意図が実際には汎用的ではないことです。メソッドは List<String> を返すように記述されています。コード内の<T>は実際には何にも影響しません。

あなたのさらなる質問に応えて - あなたは次のように書いています:

public class Sample_3 {
   public <T> List<T> testReturn(T t) {
    List<T> list = new ArrayList<T> ();
    list.add(t);
    return list;
   }

   public static void main(String a[]) {
    String s = "Gunjan";
    // this is wrong - the Sample_3 class is not generic. It does not get a generic type parameter.
    Sample_3 sample = new Sample_3<String>();
    // this is also wrong. Since the method is generic the "T" you get is the same as the "T" that 
    // goes into the method. Here your String output type does not match the input type of the method,
    // which you've set here as a Sample_3 object
    List<String> list =(List<String>) sample.testReturn(sample);

}

ジェネリック パラメーター T は、変化する可能性のある型を設定します。上記のようにメソッド レベルで行うことも、クラス レベルで行うこともできます。

public class Sample_3<T> {
   public List<T> getList(){ ... }
}

例えば

 List<Integer> l = new Sample_3<Integer>().getList();
 List<String> s = new Sample_3<String>().getList();
 List<Calendar> c = new Sample_3<Calendar>().getList();
于 2012-07-18T17:47:18.550 に答える
3

署名を作成する必要があります。

public List<String> testReturn()

メソッド宣言で使用<T>すると、渡されたパラメーターの 1 つに基づいて、メソッドでジェネリック型を使用することがコンパイラーに伝えられます。 type でパラメーターを渡していTないため、コンパイラーは型に解決できませんT

于 2012-07-18T17:40:44.887 に答える
1

T のリストの戻り値の型を指定していますが、文字列のリストを返しています。簡単な修正は次のとおりです。

public List<String> testReturn(){
  List<String> list = new ArrayList<String>();
  // add stuff to list;
  return list;
}

実際、ジェネリックの目的は、クラス (つまりサンプル) を生成して、その新しいインスタンスを作成できるようにすることですが、各インスタンスで処理するオブジェクトの種類を指定することです。Java はコンパイル時にこれらのジェネリックをチェックします。リストを例にとると、ジェネリクスがなければ、リストにどのオブジェクトを入れるかは気にしません。つまり、警告を表示せずに Double を入れる可能性があります。 get() を呼び出します。特定のオブジェクトに限定された List の新しいクラスまたは実装を作成できます。たとえば、StringList は文字列のみを受け入れることができますが、これには時間がかかり、保守が困難になる可能性があります。代わりに、Javaジェネリックを使用すると、特定のリストへの入力/特定のリストからの出力を特定のクラス(およびそのクラスの実装)に制限できます-たとえば

たとえば、サンプルを生成するには:

public class Sample<T> {
  public List<T> makeEmptyList(){
    return new ArrayList<T>();
  }
}

静的メソッドでジェネリックを指定することもできますが、ジェネリック型をオブジェクトまたはクラス参照として渡す必要があります。

public static <T> List<T> makeAndAddToList(T t){
  List<T> list = new ArrayList<T>();
  list.add(t);
  return list;
}

public static <T> List<T> makeEmptyList(Class<T> clazz){
  return new ArrayList<T>();
}

あなたの場合、 Sample クラスが文字列とリストの処理に制限されるべきか、それともジェネリックにする必要があるかは明確ではありません。

詳細については、Java チュートリアルをご覧ください。

于 2012-07-18T17:50:55.990 に答える
1

最初に尋ねる質問は、メソッド内でList<T>明示的に を作成しているときに、メソッドが戻ると宣言しているのはなぜList<String>ですか? この例では、ジェネリックを使用しても何も得られません。解決しようとしている他のシナリオはありますか?

簡単な教訓として、Java がクラスをコンパイルするとき、ジェネリックはバイトコードから削除されます。したがって、最初はエディターで次のように表示される場合があります。

public <T> List<T> testReturn(){
}
public List<String> testReturn2(){
}

バイトコードにコンパイルすると、次のようになります。

public List testReturn(){
}
public List testReturn2(){
}

これは型消去として知られています。ジェネリックの目的は、コンパイル時のパラメーター チェックを可能にすることで、実行時に例外を削除することです。実行時エラーを生成する非汎用コードの例は次のとおりです。

List list = new ArrayList();
list.add("Hello World");
list.add(Integer.valueOf(42));
for (int i = 0; i < list.size(); i++) {
    String str = (String) list.get(i);
}

List に配置された String と Integer は互換性のない型です。ジェネリックは、この種の安全でないアクセス/データ入力を禁止します (ただし、何かをキャストすると常に信じます)。

一般的な「display()」メソッドは次のようになります。

public static void main(String a[]) {
    List<String> list = new ArrayList<String>();
    list.add("Gunjan");
    list.add("Shah");

    new Sample_2().display(list);
}

public <T> void display(List<T> list) {
    for (T t : list) {
        System.out.println(t);
    }
}

ジェネリック メソッドでジェネリックを使用する場合は、ジェネリック値を、名前が付けられたオブジェクト型であるかのように参照する必要があります。T

于 2012-07-18T18:04:41.003 に答える
0

List に String オブジェクトを入れてから、 String 型の List を作成していると思います。

public List<String> testReturn(){
        List<String> list = new ArrayList<String>();
        list.add("Gunjan");
        list.add("Parth");
        list.add("Devang");
        return list; 
    }

ジェネリックはクラス、メソッド、変数で使用できますが、最も重要なのは、コレクションをよりタイプ セーフにするために使用することです。

<T>は型パラメーターと呼ばれます。これがメソッドで使用されている場合、これは、 を含むパラメーターに遭遇したときにメソッドで使用される型であることを意味しますtype T

于 2012-07-18T17:42:57.930 に答える