यह प्रश्न this StackOverflow question about unsafe casts: Java Casting method without knowing what to cast to द्वारा शामिल किया गया था।टाइप एरर के बाद फसल का सामान्य रिटर्न वैल्यू कब होता है?
- सम्मिलित प्रकार यदि डाले: सवाल मैं इस व्यवहार को मैं विशुद्ध रूप से विनिर्देश के आधार पर व्याख्या नहीं कर सकता का सामना करना पड़ा का जवाब दे जबकि
मैं ओरेकल डॉक्स पर जावा ट्यूटोरियल में निम्नलिखित बयान पाया प्रकार की सुरक्षा को संरक्षित करने के लिए आवश्यक है। The Java Tutorials: Type Erasure
यह नहीं समझाया गया है क्या "यदि आवश्यक हो तो" वास्तव में इसका मतलब है, और मैं इन डाले बिल्कुल Java Language Specification में के बारे में कोई जिक्र नहीं पाया है, इसलिए मैं प्रयोग करने के लिए शुरू कर दिया।
// Java source
public static <T> T identity(T x) {
return x;
}
public static void main(String args[]) {
String a = identity("foo");
System.out.println(a.getClass().getName());
// Prints 'java.lang.String'
Object b = identity("foo");
System.out.println(b.getClass().getName());
// Prints 'java.lang.String'
}
javac
साथ संकलित और the Java Decompiler साथ decompiled:
के कोड का निम्न भाग पर नजर डालते हैं
// Decompiled code
public static void main(String[] paramArrayOfString)
{
// The compiler inserted a cast to String to ensure type safety
String str = (String)identity("foo");
System.out.println(str.getClass().getName());
// The compiler omitted the cast, as it is not needed
// in terms of runtime type safety, but it actually could
// do an additional check. Is it some kind of optimization
// to decrease overhead? Where is this behaviour specified?
Object localObject1 = identity("foo");
System.out.println(localObject1.getClass().getName());
}
मैं देख सकता हूँ एक डाली जो पहले में सुरक्षा टाइप सुनिश्चित करता है कि वहाँ मामला, लेकिन दूसरे मामले में इसे छोड़ा गया है। यह बिल्कुल ठीक है, क्योंकि मैं Object
टाइप किए गए चर में वापसी मान को संग्रहीत करना चाहता हूं, इसलिए कास्ट प्रकार सुरक्षा के अनुसार कड़ाई से जरूरी नहीं है। हालांकि यह असुरक्षित डाले के साथ एक दिलचस्प व्यवहार की ओर जाता है:
public class Erasure {
public static <T> T unsafeIdentity(Object x) {
return (T) x;
}
public static void main(String args[]) {
// I would expect c to be either an Integer after this
// call, or a ClassCastException to be thrown when the
// return value is not Integer
Object c = Erasure.<Integer>unsafeIdentity("foo");
System.out.println(c.getClass().getName());
// but Prints 'java.lang.String'
}
}
संकलित और decompiled, मैं कोई प्रकार डाली देख रनटाइम पर सही वापसी प्रकार सुनिश्चित करने के लिए:
// The type of the return value of unsafeIdentity is not checked,
// just as in the second example.
Object localObject2 = unsafeIdentity("foo");
System.out.println(localObject2.getClass().getName());
इसका मतलब यह है कि यदि एक सामान्य समारोह किसी दिए गए प्रकार का ऑब्जेक्ट लौटाएं, यह गारंटी नहीं है कि अंततः उस प्रकार को वापस कर देगा। उपरोक्त कोड का उपयोग कर एप्लिकेशन पहले बिंदु पर विफल हो जाएगा जहां यह को Integer
पर वापसी मान डालने के लिए प्रयास करता है, तो मुझे लगता है कि यह fail-fast principle को तोड़ता है।
संकलन के दौरान इस कलाकार को डालने वाले कंपाइलर के सटीक नियम क्या हैं जो प्रकार की सुरक्षा सुनिश्चित करते हैं और ये नियम कहां निर्दिष्ट हैं?
संपादित करें:
मुझे लगता है कि संकलक कोड में खुदाई नहीं और साबित होता है कि सामान्य कोड वास्तव में देता है यह क्या करना चाहिए की कोशिश, लेकिन यह एक assertation डाल सकता है, या कम से कम एक प्रकार , कच्चा (जो यह पहले से ही के रूप में पहली उदाहरण में देखा, विशिष्ट मामलों में करता है) सही वापसी प्रकार सुनिश्चित करने के लिए तो बाद एक ClassCastException
फेंक होगा:
// It could compile to this, throwing ClassCastException:
Object localObject2 = (Integer)unsafeIdentity("foo");
मैं इस विषय पर एक विशेषज्ञ नहीं हूं, लेकिन मुझे नहीं लगता कि संकलक इस मामले में कोई जांच कर सकता है क्योंकि (1) जब यह लाइन 'रिटर्न (टी) एक्स;' देखता है, तो इसका कोई रास्ता नहीं है सांख्यिकीय रूप से जानने के लिए कि 'x' को' टी' में परिवर्तित नहीं किया जा सकता है; और (2) जब आप वास्तव में 'unsafeIdentity' कहते हैं, तो संकलक यह नहीं जानता कि यह असफल हो जाएगा क्योंकि यह विधि के कोड में नहीं पहुंचाएगा और विफलताओं की तलाश करेगा। असल में, मुझे लगता है कि इसका मतलब है कि विधि में '(टी) 'कास्ट बेकार है। – ajb
धन्यवाद @ajb, निश्चित रूप से (टी) को कास्ट करना बेकार है, यह वास्तव में एक न्यूनतम उदाहरण है। लेकिन यह आसानी से बाहरी कार्य को 'ऑब्जेक्ट ओ = (इंटीजर) असुरक्षितता ("foo") में संकलित कर सकता है;', और वह 'क्लासकास्ट अपवाद' फेंक देगा या क्या मुझे कुछ याद आ रहा है? –
मुझे नहीं लगता कि संकलक कभी भी एक दावा सम्मिलित नहीं करेगा जब तक कि आप इसे कोड न करें, तो इसे यहां क्यों करना चाहिए? लेकिन शेष प्रश्न दिलचस्प है, +1। – 5gon12eder