मैं जेनरिक के साथ प्रयोग करना और पाया कि, मेरे आश्चर्य करने के लिए, निम्न कोड को संकलित किया गया था:सर प्रकारों का उपयोग करते समय जावा टाइपएफ़ क्यों नहीं है?
class A {}
class B extends A {}
class Generic<T> {
private T instance;
public Generic(T instance) {
this.instance = instance;
}
public T get(){ return instance; }
}
public class Main {
public static void main(String[] args) {
fArray(new B[1], new Generic<A>(new A())); // <-- No error here
}
public static <T> void fArray(T[] a, Generic<? extends T> b) {
a[0] = b.get();
}
}
मैं T
B
लिए अनुमान लगाया जा की उम्मीद करेंगे। A
B
का विस्तार नहीं करता है। तो संकलक इसके बारे में शिकायत क्यों नहीं करता?
T
Object
से अनुमानित प्रतीत होता है, क्योंकि मैं Generic<Object>
भी पास कर सकता हूं।
इसके अलावा, जब वास्तव में कोड चल रहा है, यह a[0] = b.get();
लाइन पर एक ArrayStoreException
फेंकता है।
मैं किसी भी कच्चे जेनेरिक प्रकार का उपयोग नहीं कर रहा हूं। मुझे लगता है कि इस अपवाद को संकलन समय त्रुटि, या कम से कम एक चेतावनी से बचा जा सकता था, अगर T
वास्तव में B
होने का अनुमान लगाया गया था।
जब List<...>
बराबर के साथ आगे की जांच:
public static void main(String[] args) {
fList(new ArrayList<B>(), new Generic<A>(new A())); // <-- Error, as expected
}
public static <T> void fList(List<T> a, Generic<? extends T> b) {
a.add(b.get());
}
यह उत्पादन है और इसे गलती:
The method fList(List<T>, Generic<? extends T>) in the type Main is not applicable for the arguments (ArrayList<B>, Generic<A>)
अधिक सामान्य मामले करता है:
public static <T> void fList(List<? extends T> a, Generic<? extends T> b) {
a.add(b.get()); // <-- Error here
}
संकलक सही ढंग से पहचानता है कि पहले ?
दूसरे ?
की तुलना में विरासत पदानुक्रम को आगे बढ़ा सकता है।
उदा। यदि पहले ?
B
थे और दूसरा ?
A
था तो यह सुरक्षित प्रकार नहीं है।
तो पहला उदाहरण एक समान संकलक त्रुटि का उत्पादन क्यों नहीं करता है? क्या यह सिर्फ एक निरीक्षण है? या क्या कोई तकनीकी सीमा है?
एक ही रास्ता मैं एक त्रुटि उत्पादन कर सकता है स्पष्ट रूप से एक प्रकार प्रदान कर रहा है:
Main.<B>fArray(new B[1], new Generic<A>(new A())); // <-- Not applicable
मैं वास्तव में अपने खुद के अनुसंधान के माध्यम से कुछ भी नहीं मिला, this article के अलावा 2005 से (जेनरिक से पहले) , जो सरणी covariance के खतरों के बारे में बात करता है।
ऐरे कॉन्वर्सिस एक स्पष्टीकरण की ओर इशारा करते हुए प्रतीत होता है, लेकिन मैं एक के बारे में नहीं सोच सकता।
वर्तमान JDK है 1.8.0.0_91
मुझे आश्चर्य है कि क्या आप जेनेरिक में जावा के प्रकार के मिटा के खिलाफ उछाल रहे हैं? बस एक विचार, मेरे पास करीब एटीएम देखने के लिए समय नहीं है। – Ukko