2015-11-17 8 views
16

क्या बीच का अंतर है: जेनेरिक विधि जावा 6 <T> वापसी प्रकार से पहले

public void createArray(T sample){ 
    ArrayList<T> list = new ArrayList<T>(); 
    list.add(sample); 
} 

मैंने पढ़ा है कि प्रकार का उपयोग कर हस्ताक्षर विधि से वापसी प्रकार से पहले <T> होना चाहिए

public <T> void createArray(T sample){ 
    ArrayList<T> list = new ArrayList<T>(); 
    list.add(sample); 
} 

और

लेकिन कैसे आओ मैं अभी भी <T> के बिना विधि बनाने में सक्षम हूं? अगर मैं करता हूं या नहीं डालता तो क्या प्रभाव है?

+6

जवाब दिया शायद ठीक कह रहे हैं, लेकिन ध्यान दें कि, के रूप में है, अपने 'createArray' दूसरा टुकड़ा में संकलन नहीं करता है। – Tunaki

उत्तर

20

दूसरी विधि में, प्रकार पैरामीटर आम तौर पर वर्ग घोषणा जो करने के लिए विधि अंतर्गत आता है के रूप में परिभाषित किया जाएगा:

class MyClass<T> { 
    public void createArray(T sample){ 
     ArrayList<T> list = new ArrayList<T>(); 
     list.add(sample); 
    } 
    ... 
} 

तो दूसरी विधि एक सामान्य प्रकार के अंतर्गत आता है। पहली विधि सामान्य विधि है क्योंकि यह अपने स्वयं के प्रकार पैरामीटर को परिभाषित करती है।

8

पहले मामले में, जेनेरिक पैरामीटर T विधि के लिए परिभाषित किया गया है। अन्य विधियों में एक अलग T हो सकता है।

दूसरे मामले में, सामान्य पैरामीटर T कक्षा या इंटरफ़ेस के लिए परिभाषित किया गया है। उस वर्ग या इंटरफ़ेस के भीतर सभी विधियों के समान T होना चाहिए।

कक्षा-व्यापी जेनेरिक परिभाषित करने से आप कई विधियों पर एक ही प्रकार के पैरामीटर को लागू करने की अनुमति देता है। आप सामान्य प्रकार के क्षेत्र भी प्राप्त कर सकते हैं। उदाहरण के लिए ArrayList<t> देखें।

6

दूसरे उदाहरण से, मैं अनुमान लगा रहा हूँ इस विधि इस तरह एक सामान्य वर्ग के लिए कुछ में परिभाषित किया गया है:

class SomeClass<T> { 
    public void createArray(T sample){ ... } 
} 

पहले और दूसरे उदाहरण के बीच अंतर यह है कि पहले उदाहरण में, T प्रभावी रूप से है एक "स्थानीय" प्रकार चर। आप इसे एक अलग नाम दे सकते हैं, उदा। S, यह एक छोटा सा स्पष्ट करने के:

class SomeClass<T> { 
    public <S> void createArray(S sample){ ... } 
} 

तो, S और T दोनों प्रकार चर रहे हैं, लेकिन संबंधित नहीं हैं। T कक्षा के दायरे में परिभाषित किया गया है, और इसलिए कक्षा में सभी विधियों के बीच एक ही प्रकार के संदर्भ के लिए उपयोग किया जा सकता है; S केवल विधि के दायरे में परिभाषित किया गया है।

के बजाय T नाम का उपयोग करके, आप कक्षा-स्तर प्रकार चर, T छुपा रहे हैं। इसका मतलब है कि, उदाहरण के लिए, निम्नलिखित कार्य नहीं करेगा:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    public <T> void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 

क्योंकि getWotsit के हस्ताक्षर में T और चर घोषणा T wotsit संभावित विभिन्न प्रकार का उल्लेख में T; इस और अधिक स्पष्ट है अगर आप नाम S का उपयोग बराबर कोड लिखने के लिए:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    public <S> void createArray(S sample){ 
    S wotsit = getWotsit(); 
    } 
} 

जहां तक ​​मुझे पता है हूँ, कोई रास्ता नहीं वर्ग स्तर के प्रकार चर का उल्लेख करने के लिए है अगर आप एक परिभाषित किया है एक ही नाम के साथ विधि-स्तर प्रकार चर।

हालांकि, निम्न में से दोनों ठीक होगा:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    // No additional type variable, so T is the class-level type variable. 
    public void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 

class SomeClass<T> { 
    public T getWotsit() { ... } 
    // Type variable has different name, so `T` is the class-level 
    // type variable. 
    public <S> void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 
संबंधित मुद्दे