0

次のコードが例外をスローしないのはなぜですか?

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

@SuppressWarnings("unchecked")
public class MainRunner {
    public static void main(String[] args) {
    List<String> s = new ArrayList<String>() {
        {
        add("a");
        add("1");
        add("1");
        }
    };
    // List<Integer> i = (List<Integer>) listConvertor(s, new Integer("1"));
    List<Integer> i = (List<Integer>) listConvertor(s, Integer.class);
    System.out.println(i);
    }

    @SuppressWarnings("unchecked")
    public static <T, P> List<?> listConvertor(List<T> inputList, P outputClass) {
    List<P> outputList = new ArrayList<P>(inputList.size());
    for (T t : inputList) {
        outputList.add((P) t); // shouldn't be classCastException here?
    }

    return outputList;

    }

}

List<P>の代わりに戻りたいList<?>。しかし、私が書くときList<P>、それは意味しList<Class<P>>ます。つまり、上記のケースでは を意味しますが、私はリターンとしList<Class<Integer>>て欲しいです。List<Integer>

以下のコードが必要です:(メソッドが戻ったときに再度キャストする必要がないように)

List<Integer> i =   listConvertor(s, Integer.class);
        System.out.println(i);
        }

        @SuppressWarnings("unchecked")
        public static <T, P> List<P> listConvertor(List<T> inputList, P outputClass) {
        List<P> outputList = new ArrayList<P>(inputList.size());
        for (T t : inputList) {
            outputList.add((P) t); // shouldn't be classCastException here?
        }

        return outputList;

        }

    }
4

5 に答える 5

1

いいえ、もちろん例外はスローしません。ジェネリックは、実行時ではなく、コンパイル時のチェック用です。実行時には、すべてのリストがList<Object>JVM によって暗黙的にキャストされます。


編集:あなたのコードで、

for (T t : inputList) {
  outputList.add((P) t); // shouldn't be classCastException here?
}

実際にコンパイルされます

for (Object t : inputList) {
  outputList.add((Object) t); // shouldn't be classCastException here? -- no
}

たとえば、コードを使用すると、アイテムを からに変換できないため、 a を取得i.get(0).getClass()ます(: aを. ピリオドに暗黙的にキャストできないため、同じことが当てはまります)。ClassCastExceptionStringInteger.classStringInteger

これが本当にやりたいことである場合は、キャストTするP(たとえば、文字列を数値にキャストする) 場合は、別のパターンを使用することをお勧めします。例えば ​​:

static interface ClassConverter<F,T> {
    public T convert(F o);
}

static class StringToIntConverter implements ClassConverter<String,Integer> {
    public Integer convert(String o) {
        try {
            return Integer.parseInt(o);
        } catch (NumberFormatException e) {
            return 0;
        }
    }
}

public static void main(String[] args) {
    List<String> s = new ArrayList<String>() {
        {
        add("a");
        add("1");
        add("1");
        }
    };
    // List<Integer> i = (List<Integer>) listConvertor(s, new Integer("1"));
    List<Integer> i = (List<Integer>) listConvertor(s, new StringToIntConverter());
    System.out.println(i);
    System.out.println(i.get(0).getClass().getName());
}

public static <T, P> List<P> listConvertor(List<T> inputList, ClassConverter<T, P> c) {
    List<P> outputList = new ArrayList<P>(inputList.size());
    for (T t : inputList) {
        outputList.add(c.convert(t)); // cast handled by the class method == safer
    }

    return outputList;
}

あなたがする必要があるのは、変換しClassConverterたい任意の型へのインターフェースを実装し、それをメソッドに渡すことだけです。TPlistConverter

于 2012-07-27T12:14:03.030 に答える
1

これは最小限の手間で仕事をするはずです:

public static <T, P> List<P> listConvertor(List<T> inputList, Class<P> outputClass) {
    List<P> outputList = new ArrayList<P>(inputList.size());
    for (T t : inputList) {
        if( !outputClass.isInstance(t) )
            throw new ClassCastException("Faked CCException");
        @SuppressWarnings("unchecked")
        P p = (P) t;
        outputList.add(p);
    }

    return outputList;
}
  • 呼び出し側でキャストしない
  • 不適切なタイプがソース リストにある場合は例外です。
于 2012-07-27T12:35:07.937 に答える
1
public static <T, P> List<P> listConvertor(List<T> inputList, Class<P> outputClass) {

整数オブジェクトではなく、クラス オブジェクトを渡すことに注意してください。

于 2012-07-27T12:03:22.780 に答える
0

@AHの回答と同じですが、を使用して大幅に簡素化しClass.cast()、不要なを取り除きましたT

public static <P> List<P> listConvertor(List<?> inputList, Class<P> outputClass) {
    List<P> outputList = new ArrayList<P>(inputList.size());
    for (Object t : inputList) {
        P p = outputClass.cast(t);
        outputList.add(p);
    }

    return outputList;
}
于 2012-07-27T18:07:34.813 に答える
0
import java.util.ArrayList;
import java.util.List;

public class MainRunner {
  public static void main(String[] args) {
    List<String> s = new ArrayList<String>() {
      {
        add("a");
        add("1");
        add("1");
      }
    };

    List<Integer> i = listConvertor(s, Integer.class);
    System.out.println(i);
  }

  public static <T, P> List<P> listConvertor(List<T> inputList, Class<P> outputClass) {
    List<P> outputList = new ArrayList<P>(inputList.size());
    for (T t : inputList) {
      outputList.add((P) t); // shouldn't be classCastException here?
    }

    return outputList;
  }
}
于 2012-07-27T12:03:49.057 に答える