3

解決できないジェネリックと配列型の問題に遭遇しました。これに尽きます。次のコードでは、ファクトリ メソッド ("T convert(String value)") を使用して入力ジェネリック リストの個々の要素を変換しながら、ジェネリック リストを同じジェネリック型の配列に変換する方法を教えてください。

@Test
public void test(){
    List<String> integers = Arrays.asList("1", "2", "3", "4");

    Integer[] integerArray = new TypeConverter<Integer[]>(Integer[].class).convert(integers);

    assertEquals(4, integerArray.length);
    assertEquals(1, integerArray[0].intValue());
    assertEquals(2, integerArray[1].intValue());
    assertEquals(3, integerArray[2].intValue());
    assertEquals(4, integerArray[3].intValue());
}

public class TypeConverter<T>{
    Class<T> type;

    public TypeConverter(Class<T> type) {
        this.type = type;
    }

    T convert(List<String> values){

        List output = new ArrayList();

        for (String value : values) {
            //have to use Object.class here since I cant get the non-array type of T:
            output.add(new TypeConverter(type.getComponentType()).convert(value));
        }

        return (T) output.toArray();
    }

    T convert(String value){
        //convert to an int;
        if(type == Integer.class){
            return (T) new Integer(Integer.parseInt(value));
        }
        return null;
    }
}

ご覧のとおり、私の素朴なアプローチは、単純に toArray メソッドを使用し、結果を次のようにキャストすることでした。

(T) value.toArray()

しかし、これにより ClassCastException が発生します。

java.lang.ClassCastException: [Ljava.lang.Object; [Ljava.lang.Integer にキャストできません

私が見ていないこれを解決する方法はありますか、それとも別のアプローチを取るべきですか?

編集

これが私が修正しようとしている具体的なコードです。具体的には、visitArray() メソッド:

https://github.com/johncarl81/transfuse/blob/master/transfuse/src/main/java/org/androidtransfuse/analysis/adapter/AnnotationTypeValueConverterVisitor.java

4

5 に答える 5

2

リフレクション配列と参照配列を捨てることをお勧めします。

継承のわずかな乱用:

public abstract class StringConverter<T> {

    public List<T> convert(List<String> values) {
        List<T> output = new ArrayList<>();
        for (String value : values) {
            output.add(convert(value));
        }
        return output;
    }

    public abstract T convert(String value);
}

public static StringConverter<Integer> toInteger() {
    return new StringConverter<>() {
        public Integer convert(String value) {
             return Integer.parseInt(value);
        }
    };
}
于 2012-05-18T16:20:10.047 に答える
2

List.toArray取得したい配列のタイプをパラメーターとして受け取る代替バージョンを使用できます。

toArray メソッド

Arrayクラスのメソッドで空の配列を作成することができます。

Array.newInstance

したがって、期待されるタイプを使用Array.newInstance(type, 0);して、結果をtoArrayメソッドに渡します。

編集:ジェネリック型は配列であるため、コンポーネントの型を取得する必要があります。これを試してください:

Object[] array = (Object[]) Array.newInstance(type.getComponentType(), 0);
return (T) output.toArray(array);

あなたの値変換方法には、解決方法を理解できるようにするための少しのことがあります:)

乾杯!

于 2012-05-18T16:05:09.397 に答える
2

T の配列を処理しているTため、にキャストしようとしないで、 にキャストしてみてください。T[]

于 2012-05-18T16:05:17.200 に答える
1

これは私のために働く:

import java.util.*;
import java.lang.reflect.*;

public class Foo {
    public static void main(String[] args) {
        new Foo().test();
    }

    public void test(){
        List<String> integers = Arrays.asList("1", "2", "3", "4");

        Integer[] integerArray = new TypeConverter<Integer>(Integer.class).convert(integers);

        System.out.println(Arrays.deepToString(integerArray));

    }

    public class TypeConverter<T>{
        Class<T> type;

        public TypeConverter(Class<T> type) {
            this.type = type;
        }

        T[] convert(List<String> values){

            List<T> output = new ArrayList<>();

            for (String value : values) {
                output.add(convert(value));
            }

            return output.toArray((T[]) Array.newInstance(type, output.size()));
        }

        T convert(String value){
            if(type == Integer.class){
                return (T) new Integer(Integer.parseInt(value));
            }
            else if(type == Long.class){
                return (T) new Long(Long.parseLong(value));
            }
            return null;
        }

    }
}
于 2012-05-18T16:19:55.753 に答える
0

return (T) values.toArray();する必要がありますreturn (T)output.toArray( new Integer[0])

いいえ、ハードコードする必要がありますnew Integer[0]

于 2012-05-18T16:06:18.850 に答える