उप- प्रकार मानकीकृत प्रकारों के लिए उप- प्रकार अपरिवर्तनशील है । यहां तक कि कठिन वर्ग Dog
का एक उपप्रकार है Animal
, पैरामीटरकृत प्रकार List<Dog>
का उपप्रकार नहीं है List<Animal>
। इसके विपरीत, सहसंयोजक उपप्रकार का उपयोग सरणियों द्वारा किया जाता है, इसलिए सरणी प्रकार Dog[]
का उप-प्रकार है Animal[]
।
अपरिवर्तनीय उप-योग यह सुनिश्चित करता है कि जावा द्वारा लागू किए गए प्रकार की बाधाओं का उल्लंघन नहीं किया जाता है। @Jon Skeet द्वारा दिए गए निम्नलिखित कोड पर विचार करें:
List<Dog> dogs = new ArrayList<Dog>(1);
List<Animal> animals = dogs;
animals.add(new Cat()); // compile-time error
Dog dog = dogs.get(0);
जैसा कि @ जोंन स्कीट द्वारा कहा गया है, यह कोड गैरकानूनी है, क्योंकि अन्यथा यह एक कुत्ते की उम्मीद होने पर एक बिल्ली को वापस करके प्रकार की बाधाओं का उल्लंघन करेगा।
सरणियों के लिए उपर्युक्त अनुरूप कोड की तुलना करना शिक्षाप्रद है।
Dog[] dogs = new Dog[1];
Object[] animals = dogs;
animals[0] = new Cat(); // run-time error
Dog dog = dogs[0];
कोड कानूनी है। हालाँकि, एक सरणी स्टोर अपवाद फेंकता है । एक सरणी रन-टाइम पर अपने प्रकार को वहन करती है इस तरह से जेवीएम कोवेरिएंट सबटाइपिंग के प्रकार की सुरक्षा को लागू कर सकता है।
इसे और समझने के लिए आइए javap
नीचे के वर्ग द्वारा उत्पन्न बायटेकोड को देखें:
import java.util.ArrayList;
import java.util.List;
public class Demonstration {
public void normal() {
List normal = new ArrayList(1);
normal.add("lorem ipsum");
}
public void parameterized() {
List<String> parameterized = new ArrayList<>(1);
parameterized.add("lorem ipsum");
}
}
कमांड का उपयोग करना javap -c Demonstration
, यह निम्नलिखित जावा बाइटकोड दिखाता है:
Compiled from "Demonstration.java"
public class Demonstration {
public Demonstration();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void normal();
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: iconst_1
5: invokespecial #3 // Method java/util/ArrayList."<init>":(I)V
8: astore_1
9: aload_1
10: ldc #4 // String lorem ipsum
12: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
17: pop
18: return
public void parameterized();
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: iconst_1
5: invokespecial #3 // Method java/util/ArrayList."<init>":(I)V
8: astore_1
9: aload_1
10: ldc #4 // String lorem ipsum
12: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
17: pop
18: return
}
देखें कि विधि निकायों के अनुवादित कोड समान हैं। कंपाइलर ने प्रत्येक पैरामीटर प्रकार को इसके द्वारा प्रतिस्थापित किया क्षरण । यह संपत्ति महत्वपूर्ण है जिसका अर्थ है कि यह पीछे की संगतता को नहीं तोड़ती है।
निष्कर्ष में, पैरामीटर-प्रकार के लिए रन-टाइम सुरक्षा संभव नहीं है, क्योंकि कंपाइलर प्रत्येक पैरामीटर प्रकार को अपने क्षरण द्वारा बदल देता है। यह बनाता है कि मानकीकृत प्रकार वाक्यगत शर्करा से अधिक कुछ नहीं हैं।