Odpowiedz

4

Jeśli martwisz się o ślad pamięci, możesz rozważyć przeniesienie tego pola do obiektu towarzyszącego.

Tak, każde wystąpienie klasy Foo będzie miało wartość pi - kompilator Scali nie wyeliminuje tej deklaracji. Odbicie JVM pozwala na usunięcie ostatecznych modyfikatorów na elementach klas, a obiekt Unsafe pozwala nawet na ich modyfikację. Tak więc - kompilator Scala może wytworzyć kod z zaskakującymi wynikami, usuwając to pole, więc ta optymalizacja nie jest stosowana.

... 
    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 
... 

W rzeczywistości niektóre transformacje kompilatora (np specjalizacja) może nawet usunąć końcowe modyfikatorów na członków under-the-kaptur, więc coś, co czuje final w kodzie Scala nie może być final na poziomie kodu bajtowego.

to:

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

postać:

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


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

powyżej, sposób pi dostępowe (czyli jej gettera) nie jest ostateczny.

JIT w JVM Oracle nie usunie tego elementu z reprezentacji obiektu w pamięci w środowisku wykonawczym - rozmiar środowiska wykonawczego obiektu Foo na 32-bitowej maszynie JVM będzie wynosił 16 bajtów (8 bajtów nagłówka obiektu + 4 bajty dla pola liczby całkowitej, zaokrąglone do granicy 8 bajtów). JIT może jednak zdecydować o wstawieniu wartości stałej z pola końcowego do części kodu, aby niektóre zapisy w terenie zostały wyeliminowane.

3

Nie tylko każda instancja ma pole pi, będzie miała wartość zero.

pi jest definicją wartości stałej. "Accessor" po prostu zwraca stałą.

Może to powodować problemy w warunkach oddzielnej kompilacji i wstawiania, jeśli będziesz wystarczająco mocno się starał.

{ 
    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 
} 

Wystarczy, aby przekonać się, na refleksję:

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