List <MyType>をインスタンス化する方法は?


88

どうすればこの種のものを機能させることができますか?確認できますが、確認でき(obj instanceof List<?>)ません(obj instanceof List<MyType>)。これを行う方法はありますか?



回答:


49

ジェネリックスのコンパイル時にデータ型が消去されるため、これは不可能です。これを行う唯一の可能な方法は、リストが保持するタイプを保持するある種のラッパーを作成することです。

public class GenericList <T> extends ArrayList<T>
{
     private Class<T> genericType;

     public GenericList(Class<T> c)
     {
          this.genericType = c;
     }

     public Class<T> getGenericType()
     {
          return genericType;
     }
}

おかげで、両方の項目をチェックしてチェックするために呼び出す関数にジェネリック型を渡すだけだと思います。
ロッキープーリー2012

あなたは一例で手の込んだことができます
Thirumal

31
if(!myList.isEmpty() && myList.get(0) instanceof MyType){
    // MyType object
}

7
...そして空のリストの場合は?反射?
Gewure 2017

うん。空のリストで使用できるオプションはこれだけです。stackoverflow.com/questions/1942644/...
サティッシュ

12
0要素がMyTypeであっても、他の要素は他のタイプである可能性があるため、この回答は安全ではありません。たとえば、リストがArrayList <Object>として宣言され、MyTypeが追加され、次にStringが追加された可能性があります。
AdamGawne-Cain18年

@ AdamGawne-Cain安全ではありませんが、残念ながら、リストについてあまり知らない人のための唯一の解決策です。たとえば、-をvalue返すローカル変数がありObject、それがリストであるかどうかを確認する必要があります。リストである場合は、インターフェイスのリストタイプがインスタンスであるかどうかを確認します。ここでは、ラッパーやパラメーター化されたタイプは役に立ちません。
socketByte 2018

myListはどこで宣言されていますか?
IgorGanapolsky


6

これは、空ではないのobjectインスタンスであることを確認する場合に使用できますList<T>

if(object instanceof List){
    if(((List)object).size()>0 && (((List)object).get(0) instanceof MyObject)){
        // The object is of List<MyObject> and is not empty. Do something with it.
    }
}

2
    if (list instanceof List && ((List) list).stream()
                                             .noneMatch((o -> !(o instanceof MyType)))) {}

1

ObjectのList値またはMap値の参照がコレクションのインスタンスであるかどうかを確認する場合は、必要なListのインスタンスを作成し、そのクラスを取得するだけです...

Set<Object> setOfIntegers = new HashSet(Arrays.asList(2, 4, 5));
assetThat(setOfIntegers).instanceOf(new ArrayList<Integer>().getClass());

Set<Object> setOfStrings = new HashSet(Arrays.asList("my", "name", "is"));
assetThat(setOfStrings).instanceOf(new ArrayList<String>().getClass());

あなたのポイントは何であるsetOfIntegersとはsetOfStrings
DanielM 2017年

@DanielMがサンプルを更新しました。それらの参照を使用している必要があります!ありがとう!
Marcello de Sales

1

これをジェネリックスでラップできない場合(@Martijnの回答)、冗長なリストの反復を避けるために、キャストせずに渡すことをお勧めします(最初の要素のタイプをチェックしても何も保証されません)。リストを反復するコードの各要素をキャストできます。

Object attVal = jsonMap.get("attName");
List<Object> ls = new ArrayList<>();
if (attVal instanceof List) {
    ls.addAll((List) attVal);
} else {
    ls.add(attVal);
}

// far, far away ;)
for (Object item : ls) {
    if (item instanceof String) {
        System.out.println(item);
    } else {
        throw new RuntimeException("Wrong class ("+item .getClass()+") of "+item );
    }
}

0

instanceofを使用する代わりに、偽のファクトリを使用して多くのメソッドを含めることができます。

public class Message1 implements YourInterface {
   List<YourObject1> list;
   Message1(List<YourObject1> l) {
       list = l;
   }
}

public class Message2 implements YourInterface {
   List<YourObject2> list;
   Message2(List<YourObject2> l) {
       list = l;
   }
}

public class FactoryMessage {
    public static List<YourInterface> getMessage(List<YourObject1> list) {
        return (List<YourInterface>) new Message1(list);
    }
    public static List<YourInterface> getMessage(List<YourObject2> list) {
        return (List<YourInterface>) new Message2(list);
    }
}

0

ここでの主な懸念は、コレクションが定義内の型を保持しないことです。タイプは実行時にのみ使用できます。複雑なコレクションをテストする関数を思いつきました(ただし、制約が1つあります)。

オブジェクトがジェネリックコレクションのインスタンスであるかどうかを確認します。コレクションを表すために、

  • クラスはありません、常に false
  • 1つのクラス、それはコレクションではなく、instanceof評価の結果を返します
  • Listまたはを表すためSetに、リストのタイプが次に来ます。例:{List、Integer} forList<Integer>
  • を表すためMapに、キーと値のタイプが次に来ます。例:{Map、String、Integer} forMap<String, Integer>

同じルールを使用して、より複雑なユースケースを生成できます。たとえば、を表すために、次のList<Map<String, GenericRecord>>ように呼び出すことができます

    Map<String, Integer> map = new HashMap<>();
    map.put("S1", 1);
    map.put("S2", 2);
    List<Map<String, Integer> obj = new ArrayList<>();
    obj.add(map);
    isInstanceOfGenericCollection(obj, List.class, List.class, Map.class, String.class, GenericRecord.class);

この実装は、マップ内のネストされた型をサポートしていないことに注意してください。したがって、キーと値のタイプは、コレクションではなくクラスである必要があります。しかし、それを追加するのは難しいことではありません。

    public static boolean isInstanceOfGenericCollection(Object object, Class<?>... classes) {
        if (classes.length == 0) return false;
        if (classes.length == 1) return classes[0].isInstance(object);
        if (classes[0].equals(List.class))
            return object instanceof List && ((List<?>) object).stream().allMatch(item -> isInstanceOfGenericCollection(item, Arrays.copyOfRange(classes, 1, classes.length)));
        if (classes[0].equals(Set.class))
            return object instanceof Set && ((Set<?>) object).stream().allMatch(item -> isInstanceOfGenericCollection(item, Arrays.copyOfRange(classes, 1, classes.length)));
        if (classes[0].equals(Map.class))
            return object instanceof Map &&
                    ((Map<?, ?>) object).keySet().stream().allMatch(classes[classes.length - 2]::isInstance) &&
                    ((Map<?, ?>) object).values().stream().allMatch(classes[classes.length - 1]::isInstance);
        return false;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.