मैं काम करने के लिए इस तरह की चीज कैसे प्राप्त कर सकता हूं? मैं जांच कर सकता हूं (obj instanceof List<?>)
लेकिन अगर नहीं (obj instanceof List<MyType>)
। क्या कोई तरीका है जिससे यह किया जा सकता है?
मैं काम करने के लिए इस तरह की चीज कैसे प्राप्त कर सकता हूं? मैं जांच कर सकता हूं (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
}
value
जो वापस लौटता है Object
, और मुझे जांचने की आवश्यकता है - यदि यह एक सूची है, यदि यह है, तो जांचें कि क्या सूची मेरे इंटरफ़ेस को टाइप करती है। यहां कोई रैपर या पैराट्राइज्ड प्रकार उपयोगी नहीं है।
संभवतः आपको उनके प्रकारों को जांचने के लिए प्रतिबिंब का उपयोग करने की आवश्यकता है। सूची का प्रकार प्राप्त करने के लिए: java.util.List का सामान्य प्रकार प्राप्त करें
इसका उपयोग यदि आप जाँचना चाहते हैं कि 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());
setOfIntegers
और क्या बात है setOfStrings
?
यदि इसे जेनेरिक (@ मार्टिज्न के उत्तर) के साथ नहीं लपेटा जा सकता है, तो यह अनावश्यक सूची से बचने के लिए कास्टिंग के बिना इसे पारित करना बेहतर है (पहले तत्व के प्रकार की गारंटी देता है कुछ भी नहीं)। हम प्रत्येक तत्व को कोड के टुकड़े में डाल सकते हैं जहां हम सूची को पुनरावृत्त करते हैं।
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 );
}
}
आप एक फर्जी फैक्ट्री का उपयोग कर सकते हैं जिसमें इंस्टाफॉ का उपयोग करने के बजाय कई तरीके शामिल हैं:
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>
Map
, कुंजी और मूल्य प्रकार अगले आते हैं उदाहरण के लिए {मैप, स्ट्रिंग, इंटेगर}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;
}