2012-05-25 16 views
30

एक परीक्षण के रूप में, मैं इस कोड लिखा है:यदि कोई इंट शून्य नहीं हो सकता है, तो null.asInstanceOf [int] का क्या अर्थ है?

object Ambig extends App { 
    def f(x:Int ) { println("Int" ) } 
    def f(x:String) { println("String") } 
    f(null.asInstanceOf[Int ]) 
    f(null.asInstanceOf[String]) 
    f(null) 
} 

मैं च की है कि पिछले मंगलाचरण (पर एक त्रुटि प्राप्त करने के लिए उम्मीद कर रहा था), कह रही है कि यह अस्पष्ट था। संकलक इसे स्वीकार कर लिया है, और इस उत्पादन का उत्पादन:

Int 
String 
String 

अब मैं अनुमान है कि इस तथ्य यह है कि इंट एक AnyRef, तो च का ही संस्करण है कि च के लिए काम करता है के साथ क्या करना है (शून्य) एफ है (एक्स: स्ट्रिंग)। लेकिन फिर, यदि कोई इंट शून्य नहीं हो सकता है, तो null.asInstanceOf [int] का क्या अर्थ है? प्रतिलिपि का कहना है कि यह प्रकार का प्रकार है:

scala> :type null.asInstanceOf[Int] 
Int 

लेकिन मुझे वास्तव में यह नहीं लगता कि यह कैसे काम करता है। सब के बाद, अगर मैं एक इंट करने के लिए एक स्ट्रिंग कास्ट करने के लिए प्रयास करते हैं, सब नरक टूट ढीला:

scala> "foo".asInstanceOf[Int] 
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
    at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source) 
     ... 
पाठ्यक्रम है कि उम्मीद की जा करने के लिए की

- "foo" एक इंट में नहीं बनाया जा सकता। लेकिन न तो शून्य हो सकता है, तो एक इंट काम करने के लिए क्यों खुलता है? संभवतः कुछ रूपों में मुक्केबाजी, लेकिन प्रकार अभी भी इंट है, जो शून्य नहीं हो सकता है ...

मुझे क्या याद आ रही है?

+0

ओह, और आरईपीएल या स्केलप या कुछ जादू कंपाइलर ध्वज या ... का उपयोग करके, मैं इसे अपने आप कैसे समझ सकता हूं? – AmigoNico

+0

एक और समान [प्रश्न] (http://stackoverflow.com/q/8285916/617996) ... – PrimosK

+0

हालिया spec अद्यतन पर एक नज़र डालें https://github.com/scala/scala-dist/pull/20 और https://issues.scala-lang.org/browse/SI-4437 जारी करें, जो पृष्ठभूमि की कुछ कहानी बताता है। यह सी # में 'डिफ़ॉल्ट (टी)' के साथ थोड़ा तुलनीय है, afaik। – soc

उत्तर

46

null को Int पर कास्टिंग करने का व्यवहार उस संदर्भ पर निर्भर करता है जिसमें यह किया जाता है।

सबसे पहले, यदि आप null को Int पर डालते हैं, तो इसका वास्तव में एक बॉक्सिंग पूर्णांक होता है, जिसका मान null है। यदि आप अभिव्यक्ति को ऐसे संदर्भ में रखते हैं जहां अपेक्षित प्रकार Any है (जिसे दृश्य के पीछे Object में अनुवादित किया गया है, क्योंकि JVM बाइटकोड में, एक प्राचीन प्रकार और संदर्भ संदर्भ को संदर्भित करने का कोई तरीका नहीं है), तो यह मान आगे परिवर्तित नहीं होता है - यही कारण है कि println(null.asInstanceOf[Int]) प्रिंट null

हालांकि, अगर आप एक संदर्भ में यह एक ही बॉक्स्ड पूर्णांक मान का उपयोग जहां एक आदिम Int (जावा int) की उम्मीद है, यह एक आदिम करने के लिए कनवर्ट कर दिया जाएगा, और null (संदर्भ प्रकार के लिए एक डिफ़ॉल्ट मान के रूप में) है करने के लिए परिवर्तित 0 (आदिम प्रकारों के लिए एक डिफ़ॉल्ट मान)।

यदि कोई सामान्य विधि इस कलाकार को करती है, तो स्वाभाविक रूप से, आपको null वापस मिल जाता है।

हालांकि, यदि यह विधि विशिष्ट है, तो इसका वापसी प्रकार Int (जो इस मामले में एक आदिम पूर्णांक है), इसलिए null: Any मान को पहले के रूप में एक आदिम में परिवर्तित करना होगा।

इसलिए चल रहा है:

object Test extends App { 
    println(null.asInstanceOf[Int]) 

    def printit(x: Int) = println(x) 

    printit(null.asInstanceOf[Int]) 

    def nullint[T] = null.asInstanceOf[T] 

    println(nullint[Int]) 

    def nullspecint[@specialized(Int) T] = null.asInstanceOf[T] 

    println(nullspecint[Int]) 
} 

पैदा करता है: asInstanceOf समझ बनाने के लिए नहीं है:

null 
0 
null 
0 
+0

बहुत उपयोगी जानकारी - धन्यवाद! – AmigoNico

+0

मुझे एहसास नहीं हुआ कि इंट एक आदिम प्रकार – zinking

4

ऐसा लगता है कि यह सिर्फ स्वचालित रूप से शून्य करने के लिए परिवर्तित किया गया:

scala> null.asInstanceOf[Int] 
res0: Int = 0 

और, बेशक, 0, अशक्त के विपरीत, एक Int हो सकता है।

+0

बहुत रोचक। मैं शर्मिंदा हूं कि जब मैंने null.asInstanceOf [int] के * प्रकार * के लिए प्रतिलिपि से पूछा, तो यह मेरे * मूल्य * के लिए पूछने के लिए कभी नहीं हुआ, जिसे मैंने मूर्खतापूर्वक माना था। धन्यवाद! यह रूपांतरण मुझे थोड़ा आश्चर्यचकित करता है, हालांकि - हमम। – AmigoNico

+1

यह मुझे भी आश्चर्यचकित करता है। मुझे कोई जानकारी नहीं है कि यह इरादा व्यवहार है, लेकिन यह मेरे लिए गलत लगता है। – dhg

+1

यह इच्छित व्यवहार है - आपको 'var x: x = _' से वही मान मिलता है जैसा कि आप' var x = null.asInstanceOf [X] 'से किसी भी 'X' के लिए करते हैं। –

20

यहाँ बात है। संकलन रोकने के लिए संकलक को बताने के लिए यह तरीका क्या है, और आप जो कह रहे हैं उस पर विश्वास करें।

अब, अगर आप जानना चाहते हैं कि यह 0 क्यों लौटाता है, ऐसा इसलिए है क्योंकि asInstanceOf पर काम करता है, AnyVal पर नहीं। एक AnyVal के लिए आवेदन किया है, यह बॉक्स्ड संस्करण के बजाय का उपयोग करेगा और एक बॉक्स्ड null मूल्य 0.

+0

बहुत स्पष्ट और संक्षिप्त है - धन्यवाद! – AmigoNico

0

सबसे पहले है, हम सभी इस बात से सहमत है कि हम के रूप में में http://www.scala-lang.org/api/current/index.html#scala.Null

दूसरा, दस्तावेज scala.Int को null असाइन नहीं कर सकते कारण है कि जब हम println(null.asInstanceOf[Int]) करते हैं, यह null देता है?
यह println के कार्यान्वयन की वजह से है। यह अंततः जावा String.valueOf विधि है, जो

return (obj == null) ? "null" : obj.toString(); 

है यदि आप करते हैं खोल में एक null.asInstanceOf[Int] == null, यह सच वापस आ जाएगी कहता है, लेकिन यह एक विपरीत चेतावनी है कि "प्रकार इंट और अशक्त के मूल्यों की तुलना का उपयोग कर` देता == ' हमेशा झूठी उपज होगी "। मुझे लगता है कि यह स्कैला के प्रकार के मिटावट में एक समस्या हो सकती है।

println करने के लिए केवल एक स्कैला की आवश्यकता होती है। किसी भी प्रकार, इसलिए null.asInstanceOf[Int] का कास्टिंग वास्तव में अभी तक नहीं हुआ है। तो हमें बस याद रखना होगा कि जब आप एक इंट पर null.asInstanceOf[Int] असाइन करते हैं, तो कास्ट स्केल के एरर सेमेन्टिक्स के आधार पर रनटाइम पर होती है, और यह 0 को असाइन करती है।

वैसे, आप अभी भी एक च (शून्य) किसी भी संकलन त्रुटि के बिना क्योंकि स्केला एक अंतर्निहित रूपांतरण कर रही है आप

null -> java.lang.Integer -> scala.Int 

हालांकि, आप इसे चलाने के समय में चल रही है देखेंगे के लिए कर सकते हैं।

संबंधित मुद्दे