sourcecode

목록 인스턴스 방법

copyscript 2022. 11. 6. 13:38
반응형

목록 인스턴스 방법

어떻게 하면 이런 일을 할 수 있을까요?확인할 수 있다(obj instanceof List<?>)하지만 만약 그렇다면(obj instanceof List<MyType>)방법이 있을까요?

범용 컴파일 시 데이터형이 삭제되기 때문에 불가능합니다.가능한 유일한 방법은 목록에 포함된 유형을 유지하는 일종의 래퍼를 작성하는 것입니다.

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;
     }
}
if(!myList.isEmpty() && myList.get(0) instanceof MyType){
    // MyType object
}

반사를 사용하여 그 유형을 확인해야 할 수도 있습니다.목록 유형을 가져오려면: java.util의 일반 유형을 가져옵니다.리스트

이것을 체크하려면 , 이것을 사용할 수 있습니다.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.
    }
}
    if (list instanceof List && ((List) list).stream()
                                             .noneMatch((o -> !(o instanceof MyType)))) {}

개체의 목록 또는 지도 값의 참조가 컬렉션 인스턴스인지 확인하는 경우 필요한 목록의 인스턴스를 만들고 해당 클래스를 가져옵니다.

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());

이것을 제네릭스로 포장할 수 없는 경우(@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 );
    }
}

가짜 팩토리를 사용하면, 다음의 instance를 사용하는 대신에, 많은 메서드를 포함할 수 있습니다.

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);
    }
}

여기서 가장 우려되는 것은 컬렉션이 정의에 유형을 유지하지 않는다는 것입니다.유형은 런타임에만 사용할 수 있습니다.복잡한 컬렉션을 테스트하는 기능을 생각해 냈습니다(단, 한 가지 제약이 있습니다).

개체가 일반 컬렉션의 인스턴스인지 확인합니다.컬렉션을 표현하기 위해

  • 항상 수업 없음false
  • 하나의 클래스는 컬렉션이 아니며 다음 결과를 반환합니다.instanceof평가하기
  • 를 나타내다List또는Set목록 유형은 다음에 옵니다(예: {List, Integer}).List<Integer>
  • 를 나타내다Map키 및 값 유형은 다음에 옵니다(예: {Map, String, Integer}).Map<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;
    }

언급URL : https://stackoverflow.com/questions/10108122/how-to-instanceof-listmytype

반응형