This question already has answers here:
Are static methods inherited in Java?
(15 answers)
Closed 4 years ago.
I've read Statics in Java are not inherited. I've a small program below which compiles and produces 2 2 as output when run. From the program it looks like k (a static variable) is being inherited !! What am I doing wrong?
class Super
{
int i =1;
static int k = 2;
public static void print()
{
System.out.println(k);
}
}
class Sub extends Super
{
public void show()
{
// I was expecting compile error here. But it works !!
System.out.println(" k : " + k);
}
public static void main(String []args)
{
Sub m =new Sub();
m.show();
print();
}
}
The scope in which names are looked up in includes the super class.
The name print is not found in Sub so is resolved in the Super.
When the compiler generates bytecode, the call will be made to Super.print, rather than a call on a method in Sub.
Similarly the k is visible in the sub-class without qualifying it.
There is no polymorphism here, only inheritance of the contents of a name space. Static methods and all fields do not have polymorphic dispatch in Java, so can only be hidden by sub-classes, not overridden. The post you link to in your comments is using 'inheritance' in a somewhat unconventional way, mixing it up with polymorphism. You can have polymorphism without inheritance and inheritance without polymorphism.
Sub extends Super so it can see all the public/protected/package (static) members of Super.
I guess this is what you described as "Statics in Java are not inherited"
change
static int k = 2;
to
private static int k = 2;
and your Sub program won't see 'k' anymore and won't compile;
also try to create a new 'static int k=3;' in Sub, and see what happens.
It's pretty much the same as accessing Math.PI or any other global constant (which also have public and final modifiers).
In your case you have default (package) scope.
It's independed of inheritance only the scope restricts whether it is visible.
I think you might be wrong about static variables not being inherited. I suppose some properties of it are not inherited. For instance a static var normally means that all instances of the class have access to the same place in memory.
When you inherit, the derived class does not refer to the same memory as the base class.
Static member can be static data member and static method which can be accessed without using the object. It is used by nested class
Related
If I have three classes as follows:
package com.Bob.Marley;
public class SuperClass{
protected int x = 0;
}
package com.Bob.Marley;
public class SubClass extends SuperClass{
protected int x = 1;
}
package com.Bob.Marley;
public class TestClass{
public static void main (String[] args){
SubClass s = new SubClass();
//print 1
System.out.println(s.x);
//how do I print the superclass variable?
//I know inside SubClass I can access it with plain old super.x
//but what about outside the subclass with a new object.
}
}
So the question is how would I print out 0 from the superclass of the new object s created in a separate class. System.out.println(s.super.x); does not work. I don't think it changes anything but I am using java 8.
The expression s.super.x is invalid here. Whenever you prefix a super.x with something, it should be a type name, not a variable name, e.g. SuperClass.super.x. However, this would be valid only inside the subclass for accessing the superclass of the enclosing class, which does not exist here.
Cast x to be a SuperClass so you can access the x declared in Superclass.
System.out.println( ((SuperClass) s).x);
or
SuperClass sc = (SuperClass) s;
System.out.println(sc.x);
This works because variable access is statically binded. The type of the variable or expression determines the scope searched for variable access.
TL;DR: if you introduce a new field in a subclass, don't re-use a field name from the parent class. You gain nothing, only confusion and problems.
If I understand correctly, you want SubClass instances to have two fields, one inherited from the SuperClass (for the discussion, let's rename that to superX to make things clearer), and one from the subclass itself (let's rename that to subX).
For a given SubClass instance, you want to be able to access both fields, superX and subX (of course, using different expressions). What makes things difficult in your code sample, is the fact that you chose to give both of them the same name x.
So, if you really want your instances to carry both fields, I'd recommend to rename them, so you don't have to use ugly tricks like casting to the SuperClass.
public class SuperClass{
protected int superX = 0;
}
public class SubClass extends SuperClass{
protected int subX = 1;
}
But, if x stands for the same property with the same meaning for both the super and the sub class, just with different initial values, then it doesn't make sense to have two different fields, and you should change the code to become:
public class SuperClass{
protected int x = 0;
}
public class SubClass extends SuperClass{
// constructor initializes the x field with 1.
public SubClass(){
x = 1;
}
}
Of course, then it's impossible to get two different values from a single instance of SubClass.
This question already has answers here:
Are static variables inherited
(4 answers)
Closed 4 years ago.
I am learning interfaces in java and the source from which i am learning clearly says that static variables do not get inherited. But for some reason, I am able to access that static variable without adding the interface name before it. I want to know why is this happening and an in depth explanation of whats going on !!!? plzz help
class StaticMethods {
public static void main(String [] com) {
TourClient t = new TourClient(); // i made this a class variable in place of interface variable just for demonstration
t.check();
}
}
interface Tour {
///This stuff is just for display, doesn't play a role
static float minimalCost = 50000;
static float maximumCost = 1000000;
static float recommendedRating = 3.9f;
static int minimumVisitingPlaces = 4;
}
interface DubaiTour extends Tour {
static float Rating = 4.4f;
}
class TourClient implements DubaiTour{
void check() {
System.out.println(Rating); // This is not giving me any errors!!
}
}
NOTE :- I found a stack overflow page Does static variable inherited?
, but this does not explain in depth why is this happening, which doesn't help me
Static variables are inherited.
Once again - static variables are inherited - BUT you shouldn't use them. The reason why is, if you build your program. For optimization, your TourClient class variables get substituted with the constants. The line System.out.println(Rating) gets replaced with System.out.println(4.4) - all is well. If you edit your interface and change a variable to, say, 5.5, it won't get updated in your TourClient class. It will probably still print 4.4. When you use static variables in an interface, you need to recompile EVERYTHING. Not just the files you change.
This question already has answers here:
Why does Java bind variables at compile time?
(4 answers)
Closed 7 years ago.
class A {int x = 5;}
class B extends A {int x = 10;}
class D {
public static void main(String[] args){
A b0 = new B();
System.out.print(b0.x);
}
}
I am wondering why this code prints 5 instead of 10.
If I instead write the following, converting the variables x to methods, it works more as I'd expect, and prints out 10, since at compile time it merely checked if b0's static type, A, has a method x, and then at runtime, uses b0's dynamic type, B, to run x.
class A {int x() {return 5;}}
class B extends A {int x() {return 10;}}
class D {
public static void main(String[] args){
A b0 = new B();
System.out.print(b0.x());
}
}
My theory is that instance variables are looked up statically unlike methods, but I am not sure about why that would be.
Thanks!
In B the field x from A is shadowed(hidden) not overriden. To answer "why that would be" references to the docs here and here. The compiler will pick one of the 2 instances of x according to the type of the containing object. And b0 is of type A
A b0 = new B();
When you define (getter) methods on the other hand these can override methods with the same signature in the parent class. Another nasty surprise is that a field in the parent class is shadowed even if it's a different type.
Shadowing of members is considered a bad practice as it tends to confuse developers.
Because you are accessing the variable x from the class A, since b0 is defined as A. It is called hiding a variable, and not as you might suspect overriding a variable, which is not possible in java. You would get your expected result if you would access x from b0 by using a typeCast.
A b0 = new B();
System.out.print(((B)b0).x);
By using a typeCast you would be accessing the variable x from the class B now.
for further information you could read through JLS 8.3
Static fields are not inherited, they do not override each other, they shadow each other. When you directly access Static field of the same name in your case, the field of superclass hides the other field and you have two int Xes but the one of the superclass is not hidden and gets picked. Even better yet, when you call another instance of the same method and access the same static field, that is when things get very weird. The static fields get added together and you may end up with X being 5+5 = 10.
On the other hand, if you inherit non static field from superclass, there is no problem of it having different value in sub-class, because the sub-class can override the non-static super member.
Static variables and inheritance is bad, it breaks the polymorphism where you would least expect it. (Actually, if you understand concepts of your language, you expect it, but other people may not)
I want to know how many instances of a static member class can be created by the enclosing class. I assume one only, but then the following extract from Bloch doesn't make sense to me.
Quoting Joshua Bloch's Effective Java - Item 22*: Favor static member classes over nonstatic.
A common use of private static member classes is to represent components of the object represented by their enclosing class. For example, consider a Map instance, which associates keys with values. Many Map implementations have an internal Entry object for each key-value pair in the map. While each entry is associated with a map, the methods on an entry (getKey, getValue and setValue) do not need access to the map. Therefore, it would be wasteful to use a nonstatic member class to represent entries: a private static member class is best. If you accidentally omit the static modifier in the entry declaration, the map will still work, but each entry will contain a superfluous reference to the map, which wastes space and time.
He states that the map creates an Entry object for each key-value pair in the map, i.e. multiple instances of the static member class.
So my assumption is wrong! That means my understanding of static member classes is wrong. Everyone knows how a static member variable behaves, the classic static final string for instance - there is only one instance of the object.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API? Every other Collections class could then just provide it's own implementation.
[*] Just realised that it's item 18 in the PDF version of the book I have
This is a common misinterpretation of the static keyword.
When you use static with a variable it means there will be only one of these for all objects of this class or something like that.
static Object thereWillBeOnlyOne = new Object();
However, in the context of inner classes it means something completely different. A static inner class has no connection with an object of the enclosing class while a non-static inner class does.
A static inner class:
public class TrieMap<K extends CharSequence, V> extends AbstractMap<K, V> implements Map<K, V> {
private static class Entry<K extends CharSequence, V> implements Map.Entry<K, V> {
The Map.Entry class used by my TrieMap class does not need to refer to the object that created it so it can be made static to save the unnecessary reference.
A non-static inner class:
public final class StringWalker implements Iterable<Character> {
// The iteree
private final String s;
// Where to get the first character from.
private final int start;
// What to add to i (usually +/- 1).
private final int step;
// What should i be when we stop.
private final int stop;
// The Character iterator.
private final class CharacterIterator implements Iterator<Character> {
// Where I am.
private int i;
// The next character.
private Character next = null;
CharacterIterator() {
// Start at the start.
i = start;
}
public boolean hasNext() {
if (next == null) {
if (step > 0 ? i < stop : i > stop) {
next = s.charAt(i);
i += step;
}
}
return next != null;
}
The CharacterIterator inside a StringWalker object refers to the string to be iterated as s which only exists once in the StringWalker object. I can therefore create many iterators of a StringWalker and they all walk the same string.
Why this weirdness?
This seemingly illogical duality derives from the use of the static keyword in C.
In C you can (or at least used to be able to) do:
void doSomething () {
static int x = 1;
if ( x < 3 ) {
} else {
}
x += 1;
}
and each time you called the function, x would be as you left it last time around - incremented in this case.
The concept was that the static keyword indicated that the variable was scopefully enclosed by its enclosing block but semantically enclosed by its parent block. I.e. the above code was roughly equivalent to:
int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}
but x was only allowed to be referenced inside the function.
Take that concept forward into Java and things now make a little more sense. A static inner class behaves exactly like it was declared outside the class while a non-static inner bonds much more tightly to its enclosing instance - in fact it can refer to the instance directly.
Also:
class Thing {
static Object thereWillBeOnlyOne = new Object();
behaves much like
Object thereWillBeOnlyOne = new Object();
class Thing {
if it were legal.
Here endeth the lesson.
I think the Java team messed up the naming on this one. A static inner class (strictly speaking their correct name is "static nested class") is in no way different from an ordinary class except it has a fancy name (Something.MyClass instead of MyClass) and can be made private (i.e. not instantiable from other classes).
In case of Map, it was solely chosen because the name Map.Entry makes it clear that Entry relates to Map. As you suggest, it would have been perfectly reasonable to just use an ordinary class for this. The only difference is you don't get to write Map.Entry.
I think what they should have done is to use the syntax for "non-static" inner classes (i.e. just class in an enclosing class) for static nested classes, and instead invent a new keyword to create "non-static" inner classes, because it's these that behave different from normal classes. Maybe something like attached class. AFAIK the keyword static was chosen in order to avoid having too many reserved keywords, but I think it just encouraged confusion.
Yes, you can have many instances of the nested class, no matter that the nested class is static.
When the nested class is static you can create instances of it without having an instance of the enclosing class, this is one of the benefits, and basically the main difference between static and non-static nested classes.
Does this mean then that a static member class is not actually instantiated when the enclosing object is instantiated?
It's instantiated when it's constructor is called. Not any different from non-static classes. The nested class itself is loaded by the JVM, when the code first accesses it. Again this is not any different when compared to other classes, I think (not 100% sure of this though, but you can test it yourself). So I think you're kind of mixing the terms "loading the class by the JVM" and "instantiating the class".
Well in that case, what's the point of Map using a static member class for Entry? Why not just use an interface on the API?
As said, it's easier to create instances of static nested classes. You don't need an enclosing instance which is sometimes (maybe most of the times) exactly what you want.
See also:
(1) Nested Classes
(2) How can the JVM decide if a class is nested into another class?
(3) Loading of a nested class by the JVM
You can search for other references along these lines.
The reference (2) seems advanced and kind of peripheral to your question.
what's the point of Map using a static member class for Entry?
That's because, it makes the package structure logically correct.
Why not just use an interface on the API?
Now, this is a design discussion nobody would like to be dragged into.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can’t enum’s constructor access static fields?
enum Test {
e1,e2;
int i=0;
static int j=5;
Test(){
System.out.println(i+" "+j);
}
}
In the above code the constructor can access the instance variable but not the static variable J.
I have read the answer relate to other author all are saying the e1 and e2 initialized before the initialization of J( static field), But according java spec all the static field
initialized when ever the class loaded to memory, that is before running of the constructor.
So before running of Test() constructor the static variable j must be initialized. I'm not able understand the restriction, can any body make me understand.I have already read the answer of the questions Why can't enum's constructor access static fields? But I am not happy with answer like :-The constructor is called before the static fields have all been initialized.
Suppose if take another example with a simple class like enum
class Test{
public static final Test t=new Test();
static int a=5;
Test(){
System.out.println(a);
}
public static void main(String[] args) {
}
}
Here according to there argument the constructor will run before the initialization of static field and it's running also as it's print 0(As JVM did the initilization). But no compilation error or no run time problem. Then why the same thing not happen with enum.
If you imagine how your enum would actually look as a class, it makes sense:
public class Test {
// Imagine you cannot move these two statements:
public static final Test e1 = new Test();
public static final Test e2 = new Test();
int i=0;
static int j=5;
private Test(){
System.out.println(i+ " " + j);
}
static int getJ() {
return j;
}
public static void main(String[] args) {
System.out.println(Test.getJ());
}
}
This prints:
0 0
0 0
5
If you can share a concrete example (rather than a theoretical one), we could suggest how to redesign the code to achieve the desired result, despite the static field limitations.
Problem is, that instances of enum are created during inicialization of static fields. And they created before initialization of your static fields.
They must be in static array values and statically accessible, so it makes sense. And as stated in anser to "Why can't enum's constructor access static fields?", its unfortunate that this happens before all user defined static field inicialization.
But if it was swapped, you could not acces enum instances in static initialization, so it would need allowing static block both before and after creation of enum values.
I don't know whether problem is because inicialization of enum values is concern of Enum class (and handled specialy by JVM (this logic is not in Enum class itself), or because you cannot put static fields before enum values.
WHY it is that way can answer only few people (eg. Josh Bloch and Neal Gafter who are stated as authors of Enum in javadoc, and maybe some unknown others)