Do final (constant) instance (non-static) variables act like class (static) variables? - java

In the following example, the variable b is declared final, but not static. That means it's a constant instance variable. However, because it's constant, none of the Passenger objects can change its value. So isn't it better to declare it static and make it a class variable, so that there is only one copy to be used by all instantiated objects?
class Passenger {
int a;
final int b = 0;
void drive() {
System.out.println("I'm driving!");
}
}

The purpose of final but non-static variables is to have an object-wide constant. It should be initialized in the constructor:
class Passenger {
final int b;
Passenger(int b) {
this.b = b;
}
}
If you are always assigning a constant literal value (0) to the final variable, it doesn't make much sense. Using static is preferred so that you are only having a single copy of b:
static final int b = 0;
BTW I don't think having default access modifier was your intention.

It depends on the purpose of b. Usually constants are there for a specific purpose. If you make it static you could accidentally change it in some instance of that class and that will affect all the others.

If you have multiple instances of Passenger class, I would go for making it static. While this has little benefit when talking about an int variable, this could save some memory if you have complex objects. This is because a static variable belongs to a class, not to an instance, thus memory space for it will be reserved only once, and it will be referred by the class object itself, not by the instances. Of course, you should be aware that having b as a static variable means that the changes made on this variable will be reflected on all the classes that access this variable, but since you made it final this won't be the case.
Note also that with the code you've written, classes in the same package as Passenger will be able to read the b value by accessing it via Passenger.b (if static).

In java, the static attribute basically means: associated with the type itself, rather than an instance of the type.
In other words you can reference a static variable without creating instances of that type... Whereas in the case of just using final you'd need to instantiate the class.
So, yes, to answer your question, I'd say that you're right. :)

A final primitive is the same as a static final primitive (except more efficient)
A final reference to an immutable object the same as a static final reference of the same.
A final reference to a mutable object is NOT the same as a static final reference of the same.
final int i = 0;
// same as
static final int = 0;
final String hi = "Hello";
// same as
static final String hi = "Hello";
final List<String> list = new ArrayList<String>();
// is NOT the same as
static final List<String> list = new ArrayList<String>();
The only time the last example is the same is when you have a singleton. It is fairly common for singletons to be written with a confusion of static and non static fields and methods as the difference is not obvious. :|

A final variable is defined when you need a constant, so you can assign a value just once.
Using static, instead, you are defining a variable shared by all the objects of that type (like a global variable) and it is not associated with a certain object itself.

Related

JAVA: What is the advantage of static value loaded in compile time?

I write java code like this:
final int value=0;
When I use "Svace Static Analyzer" to anylyze the code,it shows:
This class contains an instance final field that is initalized to a compile-time static value, Consider making the field static---->
static final int value=0;
I know static value is loaded in compile time. Can anyone explain the advantage of compile load?
Scenario 1:
class Mango{
final int marker = 10;
}
In a class, when you declare a variable as final and initialize it during declaration, that means you do not want to modify it from anywhere.
In that case, all of the created objects of the class maintained a similar value for this variable.
On the other hand, whenever we declare a variable as static, then at the class level a single variable is created which is shared with the objects. Any change in that static variable reflects to the other objects operations.
But actually, at points 1 and 2 we want to achieve point 3's behavior implicitly.
So, java force or suggest you create only one copy of the marker variable by declaring is static also.
class Mango{
final static int marker = 10;
}
Which is memory efficient, cleaner, and non-ambiguous.
Scenario 2:
public class Mango {
final int marker;
Mango(int m){
marker = m;
}
}
This type of declaration is totally different. In that case, every instance of the Mango class has its own marker variable, and it can be initialized only one time.
The first type of declaration ensures class-level final behavior and the second type of declaration ensures the object-level final behavior.

Why should data fields be static and final

Deitel's How To Program Java book says:
A final field should also be declared static if it is initialized in its declaration to a value.
Why is that?
public class A
{
private final int x = 5;
private static final int y = 5;
}
I think x and y are the same.
What does the static qualifier matter here?
What is the advantage of the static qualifier up there for software engineering observation?
x is an instance variable while y is global.
What does that mean?
Let's look at this example:
public class A {
public A() {
System.out.println("create A");
}
}
public class B {
public B() {
System.out.println("create B");
}
}
public class C {
private static B b = new B();
private A a = new A();
}
Then a main:
public static void main(String[] args) {
C c1 = new C();
C c2 = new C();
}
Which prints:
> create B
> create A
> create A
c1 and c2 shares the same instance of B while they both create their own instance of A!
So c1.b == c2.b while c1.a != c2.a.
So summary:
there is only one and the same place/address for field b for every instance of class C (c1, c2)
but for field a there are different places/addresses in the different instances.
The example is a bit oversized with class A and B:
Even for simple fields (int, float, ...) is one and the same place/occurrence for a static field in every instance of a class.
Since it is final, it will always hold the same value.
If you don't declare it static, you will create one variable for each instance of your class. Being static means you declare the variable only once, avoiding unnecessary memory usage.
Declaring a variable as static is more memory effecient. In your example for instance, no matter how many times you create a new A(), because fields x and fields y have been declared static, they will only be allocated memory once. If you do not declare them as static, they will be allocated memory with every new class instance.
It is sensible to declare a final variable that has been initialized like yours as static because it is not able to change, and thus allocating it memory just one time is acceptable.
Essentially, it's to save memory. If the constant is always the same no matter what, then you might as well make it static so that it doesn't get created for each object. You don't want to make it static, however, if the constant is not necessarily the same for each object (for example, if your constant is initialized somewhere in a constructor).
It saves memory as it only allocates for 1 copy of the variable. If you were to make a new instance for a non-static variable for it will make a new copy for that specified instance.
Since they are final they cannot be changed so it would make sense to make them static, so when you make new instances, nothing new is allocated for the variables since they can't even be altered.

Can I define a final variable with another final?

This is more of a hypothetical question but if I have some final called A and another final B that are both ints, I can't do this:
private final int A = B/2, B = (some kind of other derived number);
I am just wondering why. Any help would be awesome. NetBeans popped up an error on this and I just want to know why it is a problem.
PS-The error that popped up said "illegal forward reference".
You are accessing variable B before you declare it. That's the reason for "illegal forward reference".
Define variable B before A
private final int B = (some kind of other derived number), A = B/2;
Pretend you're the compiler:
private final int ok. Mr user wants a "const" int
A the variable is called A
= ...here comes the value
B/2 HUH? WHAT THE HELL IS B? NO ONE TOLD ME ANYTHING ABOUT B. STUFF YOU USER. I'M OUT OF HERE...
The existing answers don't answer the underlying question:
Why can I use methods that are defined later in my source file, but does the same with variables cause a forward reference error message?
The answer is found in the JLS, more specifically JLS $12.4.1
The static initializers and class variable initializers are executed in textual order, and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope (§8.3.2.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
This question was answered here. Basically it means that you are trying to use a variable that is not initiated.
Initialize B first, then use it to initialize A
private final int B = ?, A = B/2;
illegal forward reference in java
Your code isn't failing because A and B are final. It's failing because B isn't declared/initialized yet. If you declare it first, you'll be able to use them just fine.
For example,
private final int C = 5;
private final int B = C/3;
private final int A = B/2;
This is fine because B is declared first :)
"final" just means that you can't change the variable. So something like this won't work
private final static int C = 5;
private final static int B = C/3;
private final static int A = B/2;
public static void main (String[] args) {
A = 5;
}
because now we're trying to modify A which is "final"

What's the usage of static field in Java?

From the question What's the meaning of System.out.println in Java? I found that out in System.out.println is a static field.
From C/C++ background, it's easy to understand static method, as it's the same as function in C. However, I'm not sure the use case of static field.
Is it just a way to use multiple methods without instantiating an object just as we use System.out.println without instantiating anything? Or is there any use cases for static field?
static variables/methods not only have the property of being used without instantiation, but they are also consistent across multiple instances.
For example,
public class A {
public int a = 1;
public static int b = 2;
}
Now, when I do A a1 = new A() and A a2 = new A(), A.a gets 2x the memory and is stored in the object instance, while A.b gets the memory only once and is stored outside the instance.
A prime example of this would be
a1.b = 3;
System.out.println(a2.b);
This will print 3, instead of 2, because a1 changed the value of b for the whole class, and therefore, all the instances.
A static field is a property of the class, which gets allocated on the heap and is independent of a particular object instance.
You could use a static variable to count the number of instances of a class for example.
out is an object of PrintStream.
System is a class in java.lang package
println is an instance method(not a static method) of PrintStream class
To access the field out in System without instantiating System, the field is declared static.
The System class has only one instance of the OutputStream that writes to standard output (called out) so it's a static variable. We don't need more than one instance because there's only one standard output.
A static field, is a field that is set-up and can be get without instantiating a class (using new ClassName()).
For example:
public class MyClass {
public static int number = 1;
}
With the code above, you can get the "number" field using MyClass.number.
public class MyClass {
public int number = 1;
}
Now, you need to instantiate MyClass via constructor. Since there is no constructor declared, you just use new MyClass():
MyClass cl = new MyClass();
cl.number; // <-- The number
Static fields are also known as 'class' fields (as opposed to 'instance' fields).
That means that they are accessible without you needing to instantiate the class first.
So, you can call class methods (like Math.abs() on the Math class) without having to instantiate a Math class. You can also access properties like Math.PI.
Also, changing a class property means that it affects all instances of that class, meaning that every object that was instantiated will see this value change, allowing you to affect them with a single property change.
In addition to the .out var in System, it can either be used as a shared variable that all instances of a class can update
private static int meatballsConsumed;
Or as a general-purpose shared variable
public static String thisSeemsDangerous;
Or as a constant
public static final String FLD_OF_DREAMS = "COSTNER,KEVIN";

Reasons for restrictions on assignment of final variables

Why aren't final variables default initialized? Shouldn't the default constructor initialize them to default values if you are happy with the constant be the default value.
Why must you initialized them in the constructor at all? Why can you can't you just initialize them before using them like other variables?
ex.
public class Untitled {
public final int zero;
public static void main(String[] args)
{
final int a; // this works
a = 4; // this works, but using a field doesn't
new Untitled();
}
}
Untitled.java:2: variable a might not have been initialized
Why must you initialize static final variables when they are declared? Why can't you just initialize them before using them in any other method?
ex.
public class Untitled
{
public final static int zero;
public static void main(String[] args)
{
zero = 0;
}
}
Untitled.java:8: cannot assign a value to final variable zero
I'm asking these question because I'm trying to find a logical/conceptual reason why this won't work, why it isn't allowed. Not just because it isn't.
The idea behind a final variable is that it is set once and only once.
For instance final variables, that means they can only be set during initialization, whether at declaration, in a constructor, or an instance initialization block. For the variable to be set anywhere else, that would have to take place in a non-constructor method, which could be called multiple times - that's why this is off limits.
Similarly for static final variables, they can only be set at declaration or in a static initialization block. Anywhere else would, again, have to be in a method which could be called more that once:
public static void main(String[] args)
{
zero = 0;
main(null);
}
As for your first question, I'm assuming it's an error not to explicitly set a final variable in order to avoid mistakes by the programmer.
The Java Language Specification section 8.3.1.2 spells out the rules for final member variables:
A field can be declared final (§4.12.4). Both class and instance variables (static and non-static fields) may be declared final.
It is a compile-time error if a blank final (§4.12.4) class variable is not definitely assigned (§16.8) by a static initializer (§8.7) of the class in which it is declared.
A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.
The JLS doesn't give reasons why the rules are they way they are. However, it might have come from experience in writing Java code, and the above rules are a way to avoid some common coding errors.
The concept of being final means that the variable value cannot change. If you could do as in your second example, then this variable would have been like any other one (i.e. not final)
I don't ave a good rational regarding your first question.
Because, when looking at your code, the Java compiler has no idea whether a given statement will be executed before an other statement. The only exceptions to this rule are code in constructors and implicit constructors, and that's why they're the only place that final fields can be assigned to.

Categories