कैसे करें सूची 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;
     }
}

धन्यवाद, मुझे लगता है कि मैं केवल उस फ़ंक्शन में जेनेरिक प्रकार पास करूंगा जो मैं दोनों वस्तुओं को जांचने और जांचने के लिए कह रहा हूं।
रॉकी पुली

क्या आप उदाहरण के साथ विस्तार कर सकते हैं
तिरुमल

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

7
... और एक खाली सूची के लिए? कुछ विचार?
गवूरे

यीप। खाली सूची के लिए यह एकमात्र विकल्प उपलब्ध है। stackoverflow.com/questions/1942644/…
सतीश

12
यह उत्तर सुरक्षित नहीं है, क्योंकि भले ही 0 तत्व एक MyType है, अन्य तत्व अन्य प्रकार के हो सकते हैं। उदाहरण के लिए, हो सकता है कि सूची को ArrayList <Object> के रूप में घोषित किया गया था, फिर एक MyType जोड़ा गया था, और फिर एक स्ट्रिंग जोड़ा गया था।
एडम गवने-कैन

@ एडमग्वेन-कैन यह सुरक्षित नहीं है, लेकिन दुर्भाग्य से लोगों के लिए एकमात्र समाधान सूची के बारे में बहुत कुछ नहीं जानना है। उदाहरण के लिए - मेरे पास एक स्थानीय चर है valueजो वापस लौटता है Object, और मुझे जांचने की आवश्यकता है - यदि यह एक सूची है, यदि यह है, तो जांचें कि क्या सूची मेरे इंटरफ़ेस को टाइप करती है। यहां कोई रैपर या पैराट्राइज्ड प्रकार उपयोगी नहीं है।
सॉकेटबाइट

MyList कहाँ घोषित किया जाता है?
इगोरगानापोलस्की

9

संभवतः आपको उनके प्रकारों को जांचने के लिए प्रतिबिंब का उपयोग करने की आवश्यकता है। सूची का प्रकार प्राप्त करने के लिए: java.util.List का सामान्य प्रकार प्राप्त करें


2
जहाँ तक मुझे पता है, यह केवल खेतों के लिए काम करता है, लेकिन इसे उल्लेख करने के लिए +1।
टिम पोटे

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.
    }
}


1

यदि आप सत्यापित कर रहे हैं कि किसी ऑब्जेक्ट की सूची या मानचित्र मान का संदर्भ संग्रह का एक उदाहरण है, तो बस आवश्यक सूची का एक उदाहरण बनाएं और उसकी कक्षा प्राप्त करें ...

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 ने सिर्फ नमूना अपडेट किया। यह उन संदर्भों का उपयोग करना चाहिए! धन्यवाद!
Marcello de Sales

1

यदि इसे जेनेरिक (@ मार्टिज्न के उत्तर) के साथ नहीं लपेटा जा सकता है, तो यह अनावश्यक सूची से बचने के लिए कास्टिंग के बिना इसे पारित करना बेहतर है (पहले तत्व के प्रकार की गारंटी देता है कुछ भी नहीं)। हम प्रत्येक तत्व को कोड के टुकड़े में डाल सकते हैं जहां हम सूची को पुनरावृत्त करते हैं।

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

आप एक फर्जी फैक्ट्री का उपयोग कर सकते हैं जिसमें इंस्टाफॉ का उपयोग करने के बजाय कई तरीके शामिल हैं:

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

यहां प्रमुख चिंता यह है कि संग्रह परिभाषा में प्रकार नहीं रखते हैं। प्रकार केवल रनटाइम में उपलब्ध हैं। मैं जटिल संग्रह का परीक्षण करने के लिए एक समारोह के साथ आया (हालांकि इसमें एक बाधा है)।

जाँच करें कि क्या वस्तु एक सामान्य संग्रह का उदाहरण है। एक संग्रह का प्रतिनिधित्व करने के लिए,

  • कोई वर्ग नहीं, हमेशा 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;
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.