Làm thế nào tôi có thể làm cho loại thứ này hoạt động? Tôi có thể kiểm tra nếu (obj instanceof List<?>)
nhưng không nếu (obj instanceof List<MyType>)
. Có cách nào có thể làm được điều này không?
Làm thế nào tôi có thể làm cho loại thứ này hoạt động? Tôi có thể kiểm tra nếu (obj instanceof List<?>)
nhưng không nếu (obj instanceof List<MyType>)
. Có cách nào có thể làm được điều này không?
Câu trả lời:
Điều đó là không thể vì loại dữ liệu bị xóa tại thời điểm biên dịch của generic. Cách duy nhất có thể để làm điều này là viết một số loại trình bao bọc chứa loại nào mà danh sách nắm giữ:
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
}
value
trả về Object
và tôi cần kiểm tra - nếu đó là một danh sách, nếu có, hãy kiểm tra xem loại danh sách có thể hiện trong giao diện của tôi hay không. Không có trình bao bọc hoặc kiểu tham số nào hữu ích ở đây.
Bạn có thể cần sử dụng phản xạ để kiểm tra các loại của chúng. Để nhận loại Danh sách: Nhận loại chung của java.util.List
Điều này có thể được sử dụng nếu bạn muốn kiểm tra bản sao object
của List<T>
, bản nào không trống:
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)))) {}
Nếu bạn đang xác minh xem tham chiếu của một Danh sách hoặc giá trị Ánh xạ của Đối tượng có phải là một thể hiện của Tập hợp hay không, chỉ cần tạo một thể hiện của Danh sách bắt buộc và lấy lớp của nó ...
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
và setOfStrings
?
Nếu điều này không thể được bao bọc bằng generic (câu trả lời của @ Martijn) thì tốt hơn nên chuyển nó mà không truyền để tránh lặp lại danh sách thừa (kiểm tra kiểu của phần tử đầu tiên không đảm bảo gì). Chúng ta có thể ép kiểu từng phần tử trong đoạn mã mà chúng ta lặp lại danh sách.
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 );
}
}
Bạn có thể sử dụng một nhà máy giả để bao gồm nhiều phương pháp thay vì sử dụng 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);
}
}
Mối quan tâm chính ở đây là các bộ sưu tập không giữ kiểu trong định nghĩa. Các loại chỉ có sẵn trong thời gian chạy. Tôi đã nghĩ ra một hàm để kiểm tra các bộ sưu tập phức tạp (mặc dù nó có một hạn chế).
Kiểm tra xem đối tượng có phải là một thể hiện của một tập hợp chung hay không. Để thể hiện một bộ sưu tập,
false
instanceof
đánh giáList
hoặc Set
, loại danh sách sẽ xuất hiện tiếp theo, ví dụ: {Danh sách, Số nguyên} choList<Integer>
Map
, các kiểu khóa và giá trị xuất hiện tiếp theo, ví dụ: {Bản đồ, Chuỗi, Số nguyên} choMap<String, Integer>
Các trường hợp sử dụng phức tạp hơn có thể được tạo bằng cách sử dụng các quy tắc tương tự. Ví dụ để đại diện List<Map<String, GenericRecord>>
, nó có thể được gọi là
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);
Lưu ý rằng triển khai này không hỗ trợ các kiểu lồng nhau trong Bản đồ. Do đó, loại khóa và giá trị phải là một lớp chứ không phải một tập hợp. Nhưng không khó để thêm nó.
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;
}