class Foo {
final val pi = 3
}
क्या प्रत्येक Foo
ऑब्जेक्ट में pi
सदस्य है? इसलिए मुझे साथी ऑब्जेक्ट में pi
डालना चाहिए?अंतिम vals ऑब्जेक्ट आकार में वृद्धि करते हैं?
class Foo {
final val pi = 3
}
क्या प्रत्येक Foo
ऑब्जेक्ट में pi
सदस्य है? इसलिए मुझे साथी ऑब्जेक्ट में pi
डालना चाहिए?अंतिम vals ऑब्जेक्ट आकार में वृद्धि करते हैं?
यदि आप स्मृति पदचिह्न के बारे में चिंतित हैं, तो आप इस क्षेत्र को साथी वस्तु में ले जाने पर विचार कर सकते हैं।
हां, कक्षा 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 बाइट सीमा तक गोल)। हालांकि, जेआईटी अंतिम क्षेत्र से कोड के कुछ हिस्सों में निरंतर मूल्य को रेखांकित करने का निर्णय ले सकता है, ताकि कुछ फ़ील्ड लिखने को समाप्त कर दिया जा सके।
न केवल प्रत्येक उदाहरण में 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