2017-06-14 10 views
8
public class Test { 

    static List<Object> listA = new ArrayList<>(); 

    public static void main(final String[] args) { 
     final List<TestClass> listB = new ArrayList<>(); 
     listB.add(new TestClass()); 

     // not working 
     setListA(listB); 

     // working 
     setListA(listB.stream().collect(Collectors.toList())); 

     System.out.println(); 
    } 

    private static void setListA(final List<Object> list) { 
     listA = list; 
    } 

} 

यह स्ट्रीम के साथ क्यों काम करता है और सरल सेट के लिए काम नहीं करता है?जावा java.lang.Object की सूची में विशिष्ट वर्ग की सूची जोड़ें जावा 8 धाराओं के साथ काम करता है - क्यों?

+4

'setListA (Collections.unmodifiableList (listB))' भी एक धारा बनाने की भूमि के ऊपर के बिना काम करेंगे। – Radiodef

+1

@Radiodef वह कुछ ऐसा करेगा जो पोस्ट कोड से * पूरी तरह अलग * है। (टाइप अनुमान इत्यादि से संबंधित नहीं है, लेकिन इसका उल्लेख करना चाहता था। 'नए ऐरेलिस्ट (listB) में गुजरना, पोस्ट कोड के करीब होगा, और साथ ही साथ काम करेगा) – Marco13

उत्तर

8

पहले मामले में, यह विफल रहता है क्योंकि List<TestClass>List<Object> का उपप्रकार नहीं है।

interface Stream<T> { 
    // ... 
    <R, A> R collect(Collector<? super T, A, R> collector) 
} 

और:

class Collectors { 
    // ... 
    public static <T> Collector<T, ?, List<T>> toList() 
} 

यह जावा संदर्भ से सामान्य प्रकार पैरामीटर अनुमान लगाने के लिए अनुमति देता है

दूसरे मामले के लिए, हम निम्नलिखित विधि घोषणाओं की है। इस मामले में List<Object>R, और ObjectT के लिए अनुमानित है।

इस प्रकार अपने कोड इस के बराबर है:

Collector<Object, ?, List<Object>> tmpCollector = Collectors.toList(); 
List<Object> tmpList = listB.stream().collect(tmpCollector); 
setListA(tmpList); 

1. देखें उदा here

2. उदा। देखें here या here

+0

क्या इसका मतलब यह है कि पहली "काम नहीं कर रहे" मामले में समस्या 'ऑब्जेक्ट' के लिए एक निहित कास्ट है? – Thomas

+2

@ थॉमस - यह बस इतना है कि 'सूची ' सूची 'की उप-प्रकार नहीं है, और इस प्रकार असाइनमेंट विफल हो जाता है। –

+1

क्या आप अधिक विस्तार से समझा सकते हैं क्यों सूची आर के लिए आर और ऑब्जेक्ट के लिए अनुमानित है? खासकर संदर्भ में कि 'listB.stream()' वास्तव में 'स्ट्रीम ' देता है, तो क्यों 'listB.stream() संग्रह (...)' ऑब्जेक्ट का उपयोग करें? –

2

इस लाइन

setListA(listB); 

काम नहीं करता है क्योंकि जावा में List अपरिवर्तनीय है, जिसका अर्थ List<TestClass>List<Object> नहीं फैली जब TestClass फैली Object है। अधिक जानकारी here

इस लाइन

setListA(listB.stream().collect(Collectors.toList())); 

काम करता है क्योंकि इस प्रक्रिया में हस्ताक्षर setListA(final List<Object> list) से कलेक्टर के सामान्य प्रकार के लिए जावा अनुमान वस्तु और इसलिए आप वास्तव में List<Object> वहाँ

+1

मुझे इस मामले में आविष्कार की आपकी व्याख्या पसंद है। मैं वास्तव में इस बारे में सोच रहा था, धन्यवाद। – Thomas

1

जावा जेनेरिक के प्रकार के पैरामीटर भेजने निश्चरता है जिसका अर्थ है कि इसे टाइप पैरामीटर क्लास पदानुक्रम के रूप में विरासत में नहीं लिया जा सकता है। List<TestClass> और List<Object> का सामान्य अभिभावक List<?> है।

generic inheritance

आप से kotlin & java जावा सामान्य वाइल्डकार्ड के बारे में विस्तृत जवाब देख सकते हैं। उदाहरण के लिए:

List<String> strings = new ArrayList<String>(); 
List<CharSequence> sequences = strings; // can't work 
List<? extends CharSequence> parent1 = strings; // works fine 
List<?> parent2 = strings; // works fine 
// ^--- is equaivlent to List<? extends Object> 

धाराओं दृष्टिकोण एक List<TestClass>List<Object> को बदलना है। यदि आप चाहते हैं कि यह स्ट्रीम द्वारा List को किसी अन्य List में परिवर्तित किए बिना काम करता है।अपने तरीके हस्ताक्षर के रूप में नीचे होना चाहिए, और Collection#addAll भी जावा में यह करता है:

List<?> listA = new ArrayList<>(); 

private static void setListA(List<?> list) { 
    listA = list; 
} 
संबंधित मुद्दे