Reputation: 101
I have a class like this:
public abstract class A {
public static final int FIELD;
// some methods
}
and I want to initialize the variable FIELD in a child class. I mean something like this:
public class B extends A {
FIELD = 5;
}
EDIT actually I have multiple classes that extends A and all of them have the variable FIELD but with different values; so the way I found was to refactor the variable FIELD and declare it in super class. is there any other solutions? is it possible to have something like that? thank you for helping.
Upvotes: 5
Views: 6919
Reputation: 19260
Irrespective of final keyword the single static variable won't work for multiple sub class due to single static variable get reassigned whenever new subclass is instantiated. Also the order of instantiation will still confuse further on what value lastly updated statically.
jshell> public abstract class A { public static String STATIC_SUPER_VAR = "A"; }
| created class A
jshell> public class B extends A { public B() { STATIC_SUPER_VAR = "B"; } }
| created class B
jshell> B.STATIC_SUPER_VAR
$3 ==> "A"
jshell> A.STATIC_SUPER_VAR
$4 ==> "A"
jshell> new B()
$3 ==> B@685cb137
jshell> B.STATIC_SUPER_VAR
$4 ==> "B"
jshell> A.STATIC_SUPER_VAR
$5 ==> "B"
jshell> public class C extends A { public C() { STATIC_SUPER_VAR = "C";} }
| created class C
jshell> new C()
$7 ==> C@5f2108b5
jshell> A.STATIC_SUPER_VAR
$8 ==> "C"
jshell> B.STATIC_SUPER_VAR
$9 ==> "C"
jshell> C.STATIC_SUPER_VAR
$10 ==> "C"
We can use static Map instead of single static variable.
jshell> public abstract class A {
...>
...> private static Map<Class<? extends A>, Integer> CLASS_FIELD_HOLDER = new HashMap<>();
...>
...> public A (int classSpecificInteger) {
...>
...> CLASS_FIELD_HOLDER.put(getClass(), classSpecificInteger);
...> }
...>
...>
...> public static int getClassSpecificInteger(Class<? extends A> clazz) {
...>
...> return CLASS_FIELD_HOLDER.get(clazz);
...> }
...> }
| created class A
jshell> public class B extends A {
...>
...> public B (int classSpecificInteger) {
...>
...> super(classSpecificInteger);
...> }
...> }
| created class B
jshell> public class C extends A {
...>
...> public C (int classSpecificInteger) {
...>
...> super(classSpecificInteger);
...> }
...> }
| created class C
Ensure sub class is initialised, I mean Static Map is updated before access, Else NPE
jshell> B.getClassSpecificInteger(B.class)
| Exception java.lang.NullPointerException
| at A.getClassSpecificInteger (#5:13)
| at (#7:1)
Initialised now:
jshell> new B(10);
$8 ==> B@610694f1
jshell> new C(20)
$9 ==> C@50b494a6
Access it now statically, without having FIELD in the subclass:
jshell> B.getClassSpecificInteger(B.class)
$10 ==> 10
jshell> A.getClassSpecificInteger(B.class)
$11 ==> 10
jshell> B.getClassSpecificInteger(C.class)
$12 ==> 20
Upvotes: 0
Reputation: 75
When you create a new B
object, at first, a new A
object will be created automatically and its final variables has been initialized in its default constructor; so you can no more modify their values.
Upvotes: 1
Reputation: 38910
You can not have static final variables in final class if you want to change them in derived classes.
1) Remove final keyword for FIELD attribute
2) Change the code as follows
import java.io.*;
import java.util.*;
class A {
public static int FIELD = 4;
}
class B extends A {
public B(){
this.FIELD = 5;
}
}
public class Test {
public static void main(String args[]) throws Exception {
B b = new B();
System.out.println("B value:"+b.FIELD);
}
}
Output is:
B value:5
Upvotes: 0
Reputation: 101
The point is that child classes of a super class don't have a copy of a static field declared in super class and the super class shares that between them; So there is no way to have a static variable with different values in different child classes. Therefore I will declare the variable FIELD in all of the child classes.
I got all of them from @LenceJava in the comments.
Thank you @LanceJava.
Upvotes: 5
Reputation: 695
This should work.
public class A {
public final int FIELD;
A(int a){
this.FIELD=a;
}
}
public class B extends A {
B(int a){
super(a);
}
}
Upvotes: -2
Reputation: 1107
final
variables are initialized at the time of declaration and they cannot be re initialized or modified later in the child class. final
in java means constants. Trying to modify their values causes compilation error.
Upvotes: 0
Reputation: 121998
Since it is static
and final
, at the time of initialization and or in static block you can assign value to that variable. Just no other place.
Upvotes: 1
Reputation: 81862
No this is not possible (at least not without some seriously dirty tricks)
The field has to be initialized when A
gets initialized. A
gets initialized before B
gets initialized. Anything in B
gets only executed when or after B
gets initialized.
If this would be possible, what should happen when A.FIELD
gets used, before B gets loaded?
What you could do is make the field private and not static, and provide a setter that allows only a single call to it and call it from B
.
In most cases like this there is a much cleaner solution to the real problem, but since you didn't mention the real problem you try to solve we can't help on that front.
Upvotes: 1