निम्नलिखित 2 पंक्तियों में क्या अंतर है?जावा जेनेरिक विधि सीमाएं
public static <T extends Comparable<? super T>> int methodX(List<T> data)
public static <T> int methodX(List<? extends Comparable<? super T>> data)
निम्नलिखित 2 पंक्तियों में क्या अंतर है?जावा जेनेरिक विधि सीमाएं
public static <T extends Comparable<? super T>> int methodX(List<T> data)
public static <T> int methodX(List<? extends Comparable<? super T>> data)
आपका पहला विकल्प एक "सख्त" parametrisation है की तरह अवधारणाओं का प्रयोग नहीं करता। मतलब, आप प्रतिबंधों के समूह के साथ T
कक्षा को परिभाषित कर रहे हैं, और उसके बाद इसे List
के साथ उपयोग करें। आपकी दूसरी विधि में, पैरामीटर वर्ग T
कोई शर्त नहीं है, और List
s वर्ग पैरामीटर पैरामीटर T
के संदर्भ में परिभाषित किया गया है।
दूसरा तरीका है, साथ ही वाक्य रचना अलग है, पहला विकल्प के T
के बजाय एक ?
साथ क्योंकि पैरामीटर परिभाषा आप प्रकार पैरामीटर T
परिभाषित कर रहे हैं नहीं बल्कि इसे का उपयोग, इसलिए दूसरी विधि के रूप में विशिष्ट नहीं किया जा सकता ।
इससे बाहर आने वाला व्यावहारिक अंतर विरासत में से एक है। आपका पहला विधि, एक प्रकार है कि एक सुपर वर्ग ही की के बराबर है होना करने के लिए है, जबकि दूसरे प्रकार केवल करने के लिए तुलनीय होने की जरूरत की जरूरत है बिना शर्त/असंबंधित T
:
public class Person implements Comparable<Number> {
@Override
public int compareTo(Number o) {
return 0;
}
public static <T extends Comparable<? super T>> int methodX(List<T> data) {
return 0;
}
public static <T> int methodY(List<? extends Comparable<? super T>> data) {
return 0;
}
public static void main(String[] args) {
methodX(new ArrayList<Person>()); // stricter ==> compilation error
methodY<Object>(new ArrayList<Person>());
}
}
आप की Comparable
को बदलते हैं Person
Object
या Person
(बेस क्लास का विरासत वृक्ष) की तुलना करने में सक्षम होने के लिए methodX
भी काम करेगा।
पहली विधि तत्व होंगे जो ही वर्ग या इसके एक महाप्रकार के खिलाफ तुलना की जा सकती की एक सूची की उम्मीद है। कहो, वास्तविक संख्या संख्या के किसी भी प्रकार की तुलना में किया जा सकता है:
class Real extends Number implements Comparable<Number> {
public int compareTo(Number o) ...
}
थोड़ा अधिक प्रतिबंधात्मक, लेकिन अभी भी अपने पहले विधि के लिए स्वीकार्य है निम्नलिखित:
class Real extends Number implements Comparable<Real> {
public int compareTo(Real o) ...
}
लेकिन दूसरी विधि वास्तव में है नहीं इस संस्करण से बहुत अलग:
public static int methodY(List<? extends Comparable<?>> data) ...
है कि कहने के लिए है, तो आप एक अनाम वाइल्डकार्ड ?
साथ T
जगह ले सकता है यह केवल प्रयोग किया जाता है क्योंकि एक बार विधि हस्ताक्षर में। यह एक ही कक्षा या एक वस्तु के ही वर्ग, आदि
कॉल करने के लिए, 2 संस्करण लगभग
public static <T, X extends Comparable<? super T>> int methodX(List<X> data)
के बराबर है एक फोन करने वाले एक आर्ग जिसका ठोस प्रकार List<Foo>
साथ यह कहता है मान लीजिए। टाइप अनुमान अनुमानित होगा कि X=Foo
।फिर हम X
के से टी के बारे में एक नया समीकरण प्राप्त बाध्य
=>
Foo <: Comparable<? super T>
(A <: B
का मतलब है एक बी के एक उप-प्रकार है)
तो Foo
बिल्कुल तुलनीय है, यह लगभग निश्चित रूप से implements Comparable<Foo>
[2]
=>
Comparable<Foo> <: Comparable<? super T>
=>
T <: Foo
अधिक जानकारी के बिना, अनुमान T=Foo
चुनता है।
इसलिए कॉलर के पीओवी से, दोनों संस्करण वास्तव में अलग नहीं हैं।
विधि निकाय के अंदर, दूसरे संस्करण में पैरामीटर X
टाइप करने की सुविधा नहीं है, जो एक सिंथेटिक चरण संकलन चरण में पेश किया गया है। इसका मतलब है कि आप केवल data
से पढ़ सकते हैं।
X x = data.get(0);
data.set(1, x);
संस्करण # 2 में असंभव हैं; T
के साथ संस्करण # 1 में ऐसी कोई समस्या नहीं है।
लेकिन हम # 2 के लिए # 1
<T1> method1(List<T1> data){ data.set(...); }
<T2> method2(List<?...> data)
{
method1(data);
}
(they must have difference method names; overloading not allowed since java7)
यह वह जगह है अग्रेषित कर सकते हैं क्योंकि संकलक के लिए, data
के प्रकार वास्तव में List<X>
है (यह छिपाना X
जानता है), इसलिए वहाँ का निष्कर्ष निकालते के बाद method1(data)
बुला कोई समस्या नहीं है कि T1=X
[1] JLS3, 5.1.10 कब्जा रूपांतरण
[2] Comparable
की जावाडोक के अनुसार , यह इंटरफेस प्रत्येक वर्ग की वस्तुओं पर कुल आदेश लगाता है जो इसे लागू करता है। इसका मतलब है कि Foo implements Comparable<W>
, डब्ल्यू फू या सुपर प्रकार का फू होना चाहिए। एक सुपर क्लास की वस्तुओं के बीच कुल आदेश को परिभाषित करने के लिए यह सबक्लास कार्यान्वयन के लिए काफी असंभव है। तो W
सबसे निश्चित रूप से Foo
होना चाहिए। अन्यथा मजेदार चीजें होती हैं। कुख्यात उदाहरण 'टिमस्टैम्प' है, इसका जावाडोक (अब) बताता है कि इसकी तुलना सुपरप्राइप Date