उत्तर

4

यदि आप स्मृति पदचिह्न के बारे में चिंतित हैं, तो आप इस क्षेत्र को साथी वस्तु में ले जाने पर विचार कर सकते हैं।

हां, कक्षा Foo के प्रत्येक उदाहरण में pi मूल्य होगा - स्कैला कंपाइलर इस घोषणा को खत्म नहीं करेगा। जेवीएम प्रतिबिंब आपको क्लास सदस्यों पर अंतिम संशोधक को हटाने की अनुमति देता है, और Unsafe ऑब्जेक्ट इन्हें संशोधित करने की अनुमति देता है। तो - स्कैला कंपाइलर इस क्षेत्र को हटाकर आश्चर्यजनक परिणामों के साथ कोड उत्पन्न कर सकता है, इसलिए यह अनुकूलन लागू नहीं है।

... 
    minor version: 0 
    major version: 50 
    flags: ACC_PUBLIC, ACC_SUPER 
... 
{ 
    private final int pi; 
    flags: ACC_PRIVATE, ACC_FINAL 


    public final int pi(); 
    flags: ACC_PUBLIC, ACC_FINAL 
    LineNumberTable: 
     line 243: 0 
    LocalVariableTable: 
     Start Length Slot Name Signature 
... 

वास्तव में, कुछ संकलक परिवर्तनों (जैसे विशेषज्ञता) भी अंतिम संशोधक अंडर-हुड के सदस्यों पर, समाप्त हो सकती हैं तो कुछ है कि स्काला कोड में final लगता है final बाईटकोड स्तर पर नहीं हो सकता है।

यह:

class Foo[@specialized T] { 
    final val pi: T = null.asInstanceOf[T] 
} 

हो जाता है:

... 
    public final T pi; 
    flags: ACC_PUBLIC, ACC_FINAL 
    Signature: #9       // TT; 


    public T pi(); 
    flags: ACC_PUBLIC 
    LineNumberTable: 
     line 243: 0 
    ... 

ऊपर, pi एक्सेसर विधि (अर्थात अपने गेटर) अब अंतिम है।

और न Oracle JVM में JIT रनटाइम पर स्मृति में वस्तु प्रतिनिधित्व से इस सदस्य को हटा देगा - एक 32-बिट JVM पर Foo वस्तु के क्रम आकार 16 बाइट्स हो जाएगा (8 बाइट्स आपत्ति हैडर 4 बाइट्स एक पूर्णांक क्षेत्र के लिए, 8 बाइट सीमा तक गोल)। हालांकि, जेआईटी अंतिम क्षेत्र से कोड के कुछ हिस्सों में निरंतर मूल्य को रेखांकित करने का निर्णय ले सकता है, ताकि कुछ फ़ील्ड लिखने को समाप्त कर दिया जा सके।

3

न केवल प्रत्येक उदाहरण में pi फ़ील्ड होगा, इसकी कीमत शून्य होगी।

pi एक स्थिर मूल्य परिभाषा है। "एक्सेसर" बस स्थिर देता है।

यदि आप पर्याप्त मेहनत करते हैं तो यह अलग संकलन और इनलाइनिंग की स्थितियों के तहत समस्याएं पैदा कर सकता है।

{ 
    private final int pi; 
    flags: ACC_PRIVATE, ACC_FINAL 

    public final int pi(); 
    flags: ACC_PUBLIC, ACC_FINAL 
    Code: 
     stack=1, locals=1, args_size=1 
     0: iconst_3  
     1: ireturn  
     LocalVariableTable: 
     Start Length Slot Name Signature 
       0  2  0 this LFoo; 
     LineNumberTable: 
     line 8: 0 

    public Foo(); 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0  
     1: invokespecial #14     // Method java/lang/Object."<init>":()V 
     4: return   
     LocalVariableTable: 
     Start Length Slot Name Signature 
       0  5  0 this LFoo; 
     LineNumberTable: 
     line 13: 0 
} 

बस अपने आप को समझाने के लिए, प्रतिबिंब पर:

scala> res5.tail 
res16: Iterable[reflect.runtime.universe.Symbol] = List(value pi) 

scala> res5.last.asTerm.isAccessor 
res18: Boolean = false 

scala> res5.head.asTerm.isAccessor 
res19: Boolean = true 

scala> res0 reflectField res5.last.asTerm 
res21: reflect.runtime.universe.FieldMirror = field mirror for Foo.pi (bound to [email protected]) 

scala> res21.get 
res22: Any = 0 
संबंधित मुद्दे