What are the rules dictating the inheritance of static variables in Java?
I don't understand why the contents of foo vary depending on what class you're accessing it from.
Basically it's a matter of type initialization. The value of foo
is set to "bar"
when Sub
is initialized. However, in your Testing
class, the reference to Sub.foo
is actually compiled into a reference to Super.foo
, so it doesn't end up initializing Sub
, so foo
never becomes "bar"
.
If you change your Testing code to:
public class Testing {
public static void main (String[] args) {
Sub.main(args);
System.out.println(Super.foo);
System.out.println(Sub.foo);
System.out.println(Super.foo);
}
}
Then it would print out "bar" four times, because the first statement would force Sub
to be initialized, which would change the value of foo
. It's not a matter of where it's accessed from at all.
Note that this isn't just about class loading - it's about class initialization. Classes can be loaded without being initialized. For example:
public class Testing {
public static void main (String[] args) {
System.out.println(Super.foo);
System.out.println(Sub.class);
System.out.println(Super.foo);
}
}
That still prints "foo" twice, showing that Sub
isn't initialized - but it's definitely loaded, and the program will fail if you delete the Sub.class
file before running it, for example.
Static variables in Java
From JLS
A class or interface type T will be initialized immediately before the
first occurrence of any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the field is not a constant variable (§4.12.4).
- T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.
In the First case(first set of print staments), you have access only the sName
variable only, and it's belong to Parent
Class, so the child class was not initialized.
In the second set of print statements, You have access the sName1
variable, which belongs to Child
class, so at this time, Child class was initialized.
It doesn't matter, even you have accessed the Child.sName
, it actually refers the Parent.sName
, so it won't load the Child
class.
Java and inherited static members
As others already wrote, static members are bound to the class, so you need to track the id on a class level, e.g. like this:
abstract class Parent {
private int ID;
Parent() {
ID = nextId();
}
abstract protected int nextId();
}
class Sub1 extends Parent {
private static int curID = 0;
protected int nextId() {
return curID++;
}
//...
}
class Sub2 extends Parent {
private static int curID = 0;
protected int nextId() {
return curID++;
}
//...
}
Note that this approach is not thread safe - but neither was the code in the question. You must not create new objects from the same sub class concurrently from different threads.
Java static variable in method overriding
Static variables are not inherited in java. You varibale static String a
is static which associates it to a class. Java inheritance doesn't work with static
variables.
If you absolutely want the superclass variable you could use:
System.out.println(super.a);
Here is the inheritance what you probably wish to see:
abstract class A {
String a = "superclass";
abstract void test();
}
class B extends A {
void test() {
System.out.println(a); // Output superclass
}
}
I remove the static
identifier and removed the subclass's implementation of variable a
. If you run this you'll get superclass
as output.
How fields are added from interface to class in Java?
As JLS says about static fields:
If a field is declared static, there exists exactly one incarnation of
the field, no matter how many instances (possibly zero) of the class
may eventually be created.
About fields inheritance:
A class inherits from its direct superclass and direct superinterfaces
all the non-private fields of the superclass and superinterfaces that
are both accessible to code in the class and not hidden by a
declaration in the class.
There is no special case about static fields inheritance, so they have to be inherited too.
We cannot write a good representative code sample with an interface, because of its variables are implicitly declared as static final. So, let's write a sample with superclass. Say we have:
class Base {
static int x = 15;
}
class A extends Base {}
class B extends Base {}
The x
variable is shared part of Base
class. If we think about inheritance in terms of IS-A relationship, then A
(or B
) is Base
. Then x
is shared part of A
, B
and Base
. And simple demo:
public class DemoApplication {
public static void main(String[] args) {
System.out.println(A.x++);
System.out.println(B.x);
}
}
Output:
15
16
As you can see, superclass shares a static variable with subclasses. And with an interface actually nothing changes.
Multiple inheritance quagmire - which class is instantiated?
To answer your three questions...
- An instance of the
_Foo
inD
will be returned fromnew C._Foo()
. - No, it isn't; the
_Foo
s are "members" of the classes they are declared in, so they are inherited much like variables. (In this case, like static variables.) [Spec] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2). (This is the best documentation I could muster up.) - The order is determined by what is immediately inherited by class
C
. SinceC
extendsD
,C
will inherit whateverD
has (i.e.D._Foo
). IfD
didn't declare a class called_Foo
, thenD
would inheritB
's_Foo
, and thenC
would inherit that.
Hope this helps. :)
How to provide static field to subclasses?
Does each subclass hold its own static normalizingConstants?
No, there is only one normalizingConstants
(Operation.normalizingConstants
). static
fields are tied to the class where they are declared.
If I call AddOp.normalizingConstants[0] and MinusOp.normalizingConstant[0] I want different results. How can this be achieved?
If you need different normalizingConstants
arrays, you need to declare another static variable in your sub classes, like
class MinusOp extends Operation {
private static double[] normalizingConstants;
...
Note that your normalizingConstants
fields are only accessible from within the delaring classes since they are declared private
.
Also, you should not initialize your static array in the constructor - use a static initializer instead. Otherwise, the array is re-initialized each time you create a new instance of your class (or any sub class).
Access property/constant in extended classes
Static members are resolved at compile-time, and adding an ExtendedTest.x
does not affect the also-existing BaseTest.x
, which is what the BaseTest#out()
method is linked to.
To accomplish what you're wanting, you need an overridden method:
public class BaseTest {
public String x() {
return "base";
}
public final void out() {
System.out.println(x());
}
}
public class ExtendedTest extends BaseTest {
@Override
public String x() {
return "extended";
}
}
This pattern is commonly used with an abstract method in the base class or interface to require the subclass to define an attribute such as a name or a key.
Related Topics
How to Escape the Equals Sign in Properties Files
How to Select an Item from a Dropdown List Using Selenium Webdriver with Java
Allowing the "Enter" Key to Press the Submit Button, as Opposed to Only Using Mouseclick
How to Add Days to a Date in Java
How to Enable the Java Keyword Assert in Eclipse Program-Wise
Location of Hibernate.Cfg.Xml in Project
Karate Karate-Config.Js Not a Js Function
Java Stanford Nlp: Part of Speech Labels
Performance Difference Between Java 8 Lambdas and Anonymous Inner Classes
How to Hide Cursor in a Swing Application
Difference Between Wait and Blocked Thread States
Generating All Possible Permutations of a List Recursively
Apache Poi Error Loading Xssfworkbook Class
Iteratively Compute the Cartesian Product of an Arbitrary Number of Sets