5

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.

  • why would you want to do that? why not define the variable in class B instead? Do you realise that there's only one instance of the static value? – lance-java Aug 27 '15 at 07:57
  • 1
    take a look at [this](http://stackoverflow.com/questions/663512/in-java-why-cant-i-declare-a-final-member-w-o-initializing-it-in-the-parent) – User42 Aug 27 '15 at 07:57
  • 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? – Danial Alihosseini Aug 27 '15 at 08:05
  • 1
    each subclass will NOT have it's own copy of the static field. It's shared by everything running in the whole jvm (assuming no fancy classloaders). Static fields / methods are NOT part of polymorphism. – lance-java Aug 27 '15 at 08:15
  • thank you @LanceJava. That was an important point that i didn't pay attention to that.So for this problem, should I declare the variable FIELD for all subclasses of A? – Danial Alihosseini Aug 27 '15 at 08:24
  • It depends how you plan on using FIELD. If it's just within each subclass then yes, define it in each subclass. If you want it in some abstract base class, you could pass it in the constructor. I tend to avoid inheritance and might end up creating an interface with a getter() for the field. – lance-java Aug 27 '15 at 08:38
  • thanks @LanceJava but again the getter() will not be accessible when we don't have an instance of B. – Danial Alihosseini Aug 27 '15 at 08:56
  • Chances are that if you're making it static, you're doing it wrong!!! You should instead embrace dependency injection and testability!!! – lance-java Aug 27 '15 at 09:05

8 Answers8

5

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.

1

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.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
1

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.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
1

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.

0

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.

hermit
  • 1,048
  • 1
  • 6
  • 16
0

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
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
0

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"

Solution

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
Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
-2

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);
}
}
Gaur93
  • 685
  • 7
  • 19
  • by this implementation FIELD will have its value only when an instance of B is created and the static constraint will not play its role. I mean FIELD's values will not be available when we don't have any instance of B. am I right? – Danial Alihosseini Aug 27 '15 at 08:18
  • Now the field isn't static anymore, which means, that there are as many values for FIELD as there are instances of A .... – Jens Schauder Aug 27 '15 at 08:21
  • You cannot initialize a final variable that is also static . – Gaur93 Aug 27 '15 at 08:23
  • To initialize a final variable we use a concept of initializing it via its class constructor. – Gaur93 Aug 27 '15 at 08:25