Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are `private val` and `private final val` different?

I used to think that private val and private final val are same, until I saw section 4.1 in Scala Reference:

A constant value definition is of the form

final val x = e 

where e is a constant expression (§6.24). The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition’s right-hand side e.

And I have written a test:

class PrivateVal {   private val privateVal = 0   def testPrivateVal = privateVal   private final val privateFinalVal = 1   def testPrivateFinalVal = privateFinalVal } 

javap -c output:

Compiled from "PrivateVal.scala" public class PrivateVal {   public int testPrivateVal();     Code:        0: aload_0               1: invokespecial #19                 // Method privateVal:()I        4: ireturn           public int testPrivateFinalVal();     Code:        0: iconst_1              1: ireturn           public PrivateVal();     Code:        0: aload_0               1: invokespecial #24                 // Method java/lang/Object."<init>":()V        4: aload_0               5: iconst_0              6: putfield      #14                 // Field privateVal:I        9: return } 

The byte code is just as Scala Reference said: private val is not private final val.

Why doesn't scalac just treat private val as private final val? Is there any underlying reason?

like image 470
Yang Bo Avatar asked Nov 16 '12 07:11

Yang Bo


People also ask

What is private final?

The main difference between private and final keywords in Java is that private is primarily an access modifier, which controls the visibility of variables, methods, and classes in Java applications, while final is just a modifier that enforces additional constraints on the field, method, and class in Java.

Can we use private and final together in Java?

In Java as both private and final methods do not allow the overridden functionality so no use of using both modifiers together with same method.

Is Val final Kotlin?

Most Kotlin developers would agree that a val property is equivalent to a final property in Java. What if I tell you that this is not completely true and sometimes you might need a final val ? Opposite to Java, Kotlin properties are final by default unless they are explicitly marked as open!

What is final keyword in Scala?

In Scala, Final is a keyword and used to impose restriction on super class or parent class through various ways. We can use final keyword along with variables, methods and classes.


2 Answers

So, this is just a guess, but it was a perennial annoyance in Java that final static variables with a literal on the right-hand side get inlined into bytecode as constants. That engenders a performance benefit sure, but it causes binary compatibility of the definition to break if the "constant" ever changed. When defining a final static variable whose value might need to change, Java programmers have to resort to hacks like initializing the value with a method or constructor.

A val in Scala is already final in the Java sense. It looks like Scala's designers are using the redundant modifier final to mean "permission to inline the constant value". So Scala programmers have complete control over this behavior without resorting to hacks: if they want an inlined constant, a value that should never change but is fast, they write "final val". if they want flexibility to change the value without breaking binary compatibility, just "val".

like image 59
Steve Waldman Avatar answered Sep 21 '22 06:09

Steve Waldman


I think the confusion here arises from conflating immutability with the semantics of final. vals can be overridden in child classes and therefore can't be treated as final unless marked as such explicitly.

@Brian The REPL provides class scope at the line level. See:

scala> $iw.getClass.getPackage res0: Package = package $line3  scala> private val x = 5 <console>:5: error: value x cannot be accessed in object $iw   lazy val $result = `x`  scala> private val x = 5; println(x); 5 
like image 37
Connor Doyle Avatar answered Sep 20 '22 06:09

Connor Doyle