2014-08-30 16 views
9

की परिभाषा से छोड़े गए रिटर्न प्रकार से पहले क्यों हैं I जेनरिक के बारे में प्रभावी जावा अध्याय 5 पढ़ रहे थे, विशेष रूप से जेनेरिक तरीकों को पसंद करने पर आइटम। मैंने देखा कि कभी-कभी प्रकार के पैरामीटर (कोण ब्रैकेट के बीच) वापसी प्रकार से पहले विधि घोषणा में कभी-कभी छोड़ा जाता है। वहाँ इस तरह के कई मामलों रहे हैं, लेकिन दूसरे संस्करण के पेज 135 पर उदाहरण के लिए:रिटर्न प्रकार से पहले कोण ब्रैकेट्स कभी-कभी जेनेरिक विधि

public void popAll(Collection<E> dst) { 
while (!isEmpty()) 
dst.add(pop()); 
} 

दूसरी ओर, मैं घोषणा के साथ इसी तरह के सामान्य तरीकों को देखा है

पहले एक है एक लेखन त्रुटि? यदि नहीं, तो मैं घोषणा से ब्रैकेट कब छोड़ सकता हूं?

धन्यवाद

+0

मुझे यकीन नहीं है कि इसे डुप्लिकेट के रूप में क्यों चिह्नित किया गया था। कथित डुप्ली एक पूरी तरह से अलग सवाल है। –

+5

चूंकि मैं एक वैध उत्तर पोस्ट नहीं कर सकता, इसलिए मैं एक टिप्पणी के साथ जवाब दूंगा: मेरा मानना ​​है कि अंतर यह है कि पहले मामले में पूरे वर्ग को सामान्य घोषित किया जाता है जबकि दूसरे मामले में केवल विधि सामान्य होती है। –

+0

भी फिर से खोलने के लिए वोट दिया। मैं इसे दूसरे प्रश्न से नहीं समझ सका। प्रतीत होता है, लेकिन डुप्लिकेट नहीं है। –

उत्तर

5

E है एक प्रकार चर - यह String या Integer जैसे कुछ अन्य प्रकार, के लिए में खड़ा है। तो जैसा कि आप dst.add(pop()) को यह नहीं जानते कि dst को परिभाषित किया गया था, आप popAll(Collection<E> dst) जैसे विधि घोषणा को समझ नहीं सकते हैं, यह जानने के बिना कि प्रकार और कैसे प्रकार परिवर्तनीय E परिभाषित किया गया है। popAll के मामले में, प्रकार परिवर्तनीय E कक्षा स्तर पर परिभाषित किया गया है: Stack<E>: यह ढेर में तत्वों का प्रकार है। आप अक्सर भी देखेंगे यह javadoc'd:

/**A Stack of elements 
    * 
    *@param E The type of elements in the stack */ 
public class Stack<E>{ 
    public void popAll(Collection<E> dst){ ... } 
} 

दूसरी ओर, जब आप public <E> void ... की तरह एक विधि घोषणा देखते हैं, प्रकार चर E किया जा रहा घोषित (नहीं कुछ enclosing दायरे से संदर्भित है संलग्न वर्ग की तरह)। वास्तव में जब आप अपने स्वयं के प्रकार परिवर्तनीय के साथ एक विधि देखते हैं, तो यह एक स्थिर विधि है, इसलिए E के मान को स्थापित करने के लिए कक्षा का कोई संलग्न उदाहरण नहीं है।

दोनों मामलों में, E प्रकार परिवर्तक क्या कर रहा है? यह हमें बता रहा है कि दो अलग-अलग प्रकारों को एक-दूसरे से कैसे जोड़ना है। popAll में, यह हमें बता रहा है कि जिस तत्व का संग्रह आप पॉप किए गए तत्वों को रखना चाहते हैं, उस तत्व के प्रकार से मेल खाना है जिसे आप उन्हें पॉप कर रहे हैं।

इसी तरह, पेज 136 से उदाहरण लेते:

public class ListUtils{ 
    public static <E> E reduce(List<E> list, Function<E> f, E initVal); 
} 

यहाँ, E प्रकार चर हमें बताता है कि list के तत्व प्रकार f के तर्क के प्रकार और initVal के प्रकार से मेल खाना चाहिए। आसपास के वर्ग E को हमारे लिए परिभाषित नहीं करता है, यह reduce विधि घोषणा के दायरे में केवल सार्थक है।

5

अंतर यह है कि पहले मामले में पूरी कक्षा सामान्य घोषित किया जाता है, जबकि दूसरे मामले में एकमात्र तरीका सामान्य है।

1

उत्तर है ... यह नहीं है। एक "सामान्य विधि" परिभाषित एक है कि वापसी प्रकार से पहले चर टाइप वाणी हो रहा है: अगर यह एक या अधिक प्रकार चर वाणी

एक विधि सामान्य है।(JLS 8.4.4)

इसलिए, popAll एक "सामान्य विधि" नहीं है।

चूंकि विधि प्रकार पैरामीटर E घोषित नहीं करता है, इसे एक संलग्न क्षेत्र में परिभाषित किया जाना चाहिए; लगभग निश्चित रूप से कक्षा (एक "सामान्य वर्ग") जिसमें विधि शामिल है।

संबंधित मुद्दे