As far as I know a field in Java and Scala marked as Volatile, provides the happens before relationship.
In Java it is not possible to have a local variable within a method as volatile. However the Scala compiler seems to allow, such things, as in the code bellow:
def test: Unit = {
#volatile var doNotStop = true
}
Does it actually work the same way as in Java? What are the semantics of such code? How does it look in Byte code and in the JVM during runtime?
In Java, such variable if given to a closure, could be modified by another thread, therefore, it is mandatory to be final, right?
TL;DR: The #volatile annotation looks like it is ignored when applied on a local variable, except if the variable can be escaped from this local scope inside a closure.
To make sure of this, we can checkout the bytecode corresponding to the following snippet
class Foo {
def test: Unit = {
#volatile var doNotStop: Boolean = true
}
}
The class file obtained using scalac can be decompiled using javap -c -v -p. Here's the relevant part for the test method:
public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=1
0: iconst_1
1: istore_1
2: return
LocalVariableTable:
Start Length Slot Name Signature
1 1 1 doNotStop Z
...
Note that there is no information relating to any volatile access.
If we choose to declare doNotStop as an instance variable instead, then javap shows the following field declaration with a clear volatile flag:
private volatile boolean doNotStop;
descriptor: Z
flags: ACC_PRIVATE, ACC_VOLATILE
However, your concern about the local variable escaping its scope is completely valid! Let's try this:
class Foo {
def test = {
var doNotStop: Boolean = true
() => doNotStop = false
}
}
Using javap -p (no need to look at the bytecode or flags this time) gives us the following definitions:
public class Foo {
public scala.Function0<scala.runtime.BoxedUnit> test();
public static final void $anonfun$test$1(scala.runtime.BooleanRef);
public Foo();
private static java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda);
}
You can see that the closure has been compiled into its own method named $anonfun$test$1 which takes a BooleanRef. This BooleanRef is the runtime representation for doNotStop and wraps a boolean. For more info about the last declaration, you can checkout the related Java documentation.
Now for the reveal: what if we make doNotStop volatile again?
public class Foo {
public scala.Function0<scala.runtime.BoxedUnit> test();
public static final void $anonfun$test$1(scala.runtime.VolatileBooleanRef);
public Foo();
private static java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda);
}
The class stayed mostly the same, but $anonfun$test$1 now takes a VolatileBooleanRef. Guess how its inner boolean is implemented:
volatile public boolean elem;
The semantics here are very clear: your not-so-local Boolean variable is represented as field of a BooleanRef instance at runtime. It is this field that may be marked volatile by the annotation. There you go, #volatile was useful there after all!
To answer your second question: Java's closure only close over values that are "effectively final", which would disallow this pattern where the value of doNotStop changes within the closure. You could of course implement it the same way as was done here, using an "effectively final" reference to a (Volatile)BooleanRef whose elem can be freely modified by the closure.
This compiles:
public class SandboxJava { //Java
public Integer cards;
}
But this does not:
class SandboxScala{
var cards:Int //Throws saying the class must be abstract to have undefined variables
}
Now I know the fact that vars must be initialized but why does not Scala have this functionality of having undefined variables in the first place?
In Java, a field that isn't explicitly initialized is still initialized. References are automatically initialized to null and scalar values to 0. The fact that it doesn't need to be explicit is just a kind of shorthand or syntactic sugar.
Local variables are a bit different. They're not automatically initialized, and they can be declared without initialization, but it's a compiler error to access them before initializing them.
public class Foo {
public static void main(String[] args) {
int x;
if(x == 0) {
System.out.println("Hello.");
}
}
}
Results in
Foo.java:4: error: variable x might not have been initialized
if(x == 0) {
^
Because although they look similar, they mean different things (have different "semantics"). The Scala equivalent of your Java code:
public class SandboxJava { // Java
public Integer cards;
}
is this Scala code:
class SandboxScala {
var cards:Int = _
}
This has (practically) the same semantics as your Java example. In the code above cards:
is public-accessible
is mutable (because of var)
is initialized to its "default value" (because of = _)
Note that it is precisely because cards is mutable (a var) that you can initialize cards to its "default value". That is: val cards = _ does not work, for obvious reasons (you can not change a val afterwards, so you better initialize it with something meaningful).
As other answers have noted, your Scala version is wrong (for the reason I stated above: you have to initialize a val with something).
If one corrected your Scala version with this:
class SandboxScala {
val cards:Int = SOME_INITIAL_VALUE
}
you could write something semantically equivalent in Java like this:
class SandboxJava {
public final int cards = SOME_INITIAL_VALUE
}
Note in this case that the Java compiler would also complain if you failed to provide an initial value for cards.
A val is immutable. It can never be set. What use is an uninitialized field that can never be set?
Scala doesn't have abstract modifier when it comes to def/val/var. So when such a member doesn't have a definition it's considered abstract. That's why compiler complains when you try to declare abstract member in a concrete class.
I just want to check that this is not possible/if it is possible with Java. I set-out to make a java version of template (i.e. a generic class) that could be used for a bounded string family.
public abstract class BoundedNameType<U extends Integer> extends NameType
{
private static final MAX_LEN = U;
private BoundedNameTypes( final String... parameters ){
super( MAX_LEN, parameters );
}
}//BoundedNameType
Where the parent class uses the U as a value for the MAX_LEN, e.g.
public abstract class NameType
{
private NameType( final Integer u, final String... parameters ){
this.maxLen = u;
}
}//NameType
Or perhaps go one better and make MAX_LEN is abstract protected, so I don't need a 'maxLen' member and the max value can always a static final. My efforts and reading indicate that generics in Java are types-only, so it shouldn't work. I've put links down, it is time to just use a declaration to do this; I would still like to know if there's a stricter generics way to do this!? Or that the definitive answer is "No".
See also:
Java Generics Value.<SomeValue>
How are Java generics different from C++ templates? Why can't I use int as a parameter?
That is not possible in Java. Generic parameters must be types.
Java generics are only superficially similar to C++ templates.
I want to make a class that works like String, i.e doesn't require new String("value");.
For example:
public class Number { ... }
// main
Number num = 5;
Is it possible?
Short answer is no.
The long answer, you wouldn't want that behavior.
The cool thing about a strict OO language is you can ensure that an object is an object... the problem with java is that its a class based language, and less of an OO language... which causes oddities like this.
int myInt = 5; //primitive assignment.
This is a value, it is not an object and does not conform to the standards of what an object represents in Java.
Integer myInt = new Integer(5);
is creating a new object in memory, assigning a reference to it, and then any "passing" of this object happens by reference.
There are many frameworks that can give you a semblance of this assignment, but the new lets you know that you are creating a brand new object and not simply the value of some random section of memory that happens to be declared as a string of integer bits.
Like AnthonyJClink said, you can't. But.. you can (kinda) shorten your instantiation code by not using the new keyword if you instantiate your instance in static method of your class. For example:
public class MyClass {
private MyClass(){
}
public static MyClass create(){
return new MyClass();
}
public static void main(String[] args) {
MyClass instance = MyClass.create(); // Add parameters as needed
}
}
It reminds me of methods like int b = Integer.parseInt("444"); It makes your code more readable in some cases. It really depends on your needs. This public static instantiation is also often used with singletons getInstance() methods.
No, but if you are looking to syntactic alternatives, there are some alternatives to constructors, that have their application.
Enums - not what you are looking for.
Static factory methods.
Rule x = Rules.def("abc");
Rule y = def("abc"); // Static import
public abstract class Rules { // Factory
public static Rule def(String s):
(One can drop the class name not only by a static import, but also by being inside a super class.)
class Grammar { protected Rule def(String s) { ... } }
Grammar g = new Grammar() {{
Rule x = def("abc");
}};
Builders, fluent API
Grammar g = GrammarBuilder.grammar("Pascal")
.rule("S")
.seq()
.keyword("PROGRAM");
.nont("Decl")
.nont("Block")
.endseq()
.endrule()
.rule("Decl")
...
Builders, fluent API
Grammar g = grammar("Pascal",
rule("S",
seq(
.keyword("PROGRAM");
.nont("Decl")
.nont("Block")
.endseq()
)),
rule("Decl",
...)
);
Java 8 lambdas assigning to functional interfaces
Producer<String> x = () -> "beep";
x = () -> x.apply() + x.apply();
System.out.println(x.apply());
The Java for C++ programmers tutorial says that (highlight is my own):
The keyword final is roughly
equivalent to const in C++
What does "roughly" mean in this context? Aren't they exactly the same?
What are the differences, if any?
In C++ marking a member function const means it may be called on const instances. Java does not have an equivalent to this. E.g.:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
Values can be assigned, once, later in Java only e.g.:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
is legal in Java, but not C++ whereas:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
In both Java and C++ member variables may be final/const respectively. These need to be given a value by the time an instance of the class is finished being constructed.
In Java they must be set before the constructor has finished, this can be achieved in one of two ways:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
In C++ you will need to use initialisation lists to give const members a value:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
In Java final can be used to mark things as non-overridable. C++ (pre-C++11) does not do this. E.g.:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
But in C++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
this is fine, because the semantics of marking a member function const are different. (You could also overload by only having the const on one of the member functions. (Note also that C++11 allows member functions to be marked final, see the C++11 update section)
C++11 update:
C++11 does in fact allow you to mark both classes and member functions as final, with identical semantics to the same feature in Java, for example in Java:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Can now be exactly written in C++11 as:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
I had to compile this example with a pre-release of G++ 4.7. Note that this does not replace const in this case, but rather augments it, providing the Java-like behaviour that wasn't seen with the closest equivalent C++ keyword. So if you wanted a member function to be both final and const you would do:
class Bar {
public:
virtual void foo() const final;
};
(The order of const and final here is required).
Previously there wasn't a direct equivalent of const member functions although making functions non-virtual would be a potential option albeit without causing an error at compile time.
Likewise the Java:
public final class Bar {
}
public class Error extends Bar {
}
becomes in C++11:
class Bar final {
};
class Error : public Bar {
};
(Previously private constructors was probably the closest you could get to this in C++)
Interestingly, in order to maintain backwards compatibility with pre-C++11 code final isn't a keyword in the usual way. (Take the trivial, legal C++98 example struct final; to see why making it a keyword would break code)
A const object can only call const methods, and is generally considered immutable.
const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)
A final object cannot be set to a new object, but it is not immutable - there is nothing stopping someone from calling any set methods.
final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!
Java has no inherent way of declaring objects immutable; you need to design the class as immutable yourself.
When the variable is a primitive type, final/const work the same.
const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages
In Java the final keyword can be used for four things:
on a class or method to seal it (no subclasses / overriding allowed)
on a member variable to declare that is it can be set exactly once (I think this is what you are talking about)
on a variable declared in a method, to make sure that it can be set exactly once
on a method parameter, to declare that it cannot be modified within the method
One important thing is:
A Java final member variable must be set exactly once! For example, in a constructor, field declaration, or intializer. (But you cannot set a final member variable in a method).
Another consequence of making a member variable final relates to the memory model, which is important if you work in a threaded environment.
Java final is equivalent to C++ const on primitive value types.
With Java reference types, the final keyword is equivalent to a const pointer... i.e.
//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();
//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();
Java's final works only on primitive types and references, never on object instances themselves where the const keyword works on anything.
Compare const list<int> melist; with final List<Integer> melist; the first makes it impossible to modify the list, while the latter only stops you from assigning a new list to melist.
You have some great answers here already, but one point that seemed worth adding: const in C++ is commonly used to prevent other parts of the program changing the state of objects. As has been pointed out, final in java can't do this (except for primitives) - it just prevents the reference from being changed to a different object. But if you are using a Collection, you can prevent changes to your objects by using the static method
Collection.unmodifiableCollection( myCollection )
This returns a Collection reference that gives read-access to the elements, but throws an exception if modifications are attempted, making it a bit like const in C++
Aside from having certain and subtle multi-threading properties, variables declared final don't need to be initialized on declaration!
i.e. This is valid in Java:
// declare the variable
final int foo;
{
// do something...
// and then initialize the variable
foo = ...;
}
This would not be valid if written with C++'s const.
According to wikipedia:
In C++, a const field is not only protected from being reassigned, but there is the additional limitation that only const methods can be called on it and it can only be passed as the const argument of other methods.
Non-static inner classes can freely access any field of the enclosing class, final or not.
I am guessing it says "roughly" because the meaning of const in C++ gets complicated when you talk about pointers, i.e. constant pointers vs. pointers to constant objects. Since there are no "explicit" pointers in Java, final does not have these issues.
Let me explain what I understood with an example of switch/case statement.
The values in each case statement must be compile-time constant values of the same data type as the switch value.
declare something like below (either in your method as local instances, or in your class as static variable(add static to it then), or an instance variable.
final String color1 = "Red";
and
static final String color2 = "Green";
switch (myColor) { // myColor is of data type String
case color1:
//do something here with Red
break;
case color2:
//do something with Green
break;
}
This code will not compile, if color1 is a class/instance variable and not a local variable.
This will compile if color1 is defined as static final (then it becomes static final variable).
When it does not compile, you will get the following error
error: constant string expression required
keyword "const" mean that your variable is saved in ROM (with Microprocessor). in computer, your variable is saved in RAM area for Assembly code (read only RAM). it means that your variable is not in the writeable RAM include: static memory, stack memory and heap memory.
keyword "final" mean that your variable is saved in writeable RAM, but you notice to compiler that your variable is only change only one time.
//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler
//the same in C++ the same as follows
int i =10;
const int &iFinal = i;
iFinal = 11; //error is showed here by compiler the same as above
I think, "const" is bad in performance, so Java does not use it.