I know in Java, static method can not be overriden by the subclass.
Two questions:
1. Why is that? Could anyone explain me the reason inside it?
2. Can subclass override final method in super class then?
Static methods aren't called on a particular instance - so they can't be called polymorphically. They are called on the type itself - nothing about the binding relies on any information which is only available at execution time. The point about polymorphic calls is that the method implementation which ends up being executed depends on the execution-time type of the target of the call; there's no target for static method calls, as such.
No, subclasses can't override final methods - the whole point of making a method final is to prevent it from being overridden.
Related
I would like to clarify a few things about binding and dispatch.
Binding is attaching a method call to a method signature. Dispatch is choosing over method implementations. First comes binding, then comes dispatch. OK, I got this, but:
Do instance methods that have not been overridden use static binding?
Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?
I've read lots of explanations over the last few days and it's a mess for me now. Some of them are conflicting or completely opposite from one another. From what I know all non-static, non-private and non-final methods in Java are virtual by default and must use dynamic binding and dynamic dispatch.
Binding is attaching a method call to a method signature. Dispatch is choosing over method implementations.
Binding in the sense you mean refers to overloading. Dispatch in the sense you mean refers to overriding.
First comes binding, then comes dispatch.
Yes. The compiler does the binding, the JVM does dispatching.
OK, I got this, but:
Do instance methods that have not been overridden use static binding?
No. The compiler can't tell that, except in the case of private methods, in which case it uses the invokespecial bytecode.
Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?
They don't.
From what I know all non-static, non-private and non-final methods in Java are virtual by default and must use dynamic binding and dynamic dispatch.
Correct.
Rules for binding in java:
1) Call to a Static method is Statically binded.
2) Call to a constructor is statically binded.
3) Call to non-static methods are dynamically binded:
Exceptions:
3.a) Call to private , non-static method is statically binded.
3.b) non-private, non-static method called using super in subclass is also statically binded.
So for 1st question i.e. Do instance methods that have not been overridden use static binding?
Answer is No. If the method has not been overridden, but it can be(in future). And as it is an instance method it can be called using instance(dynamic binding) or invoked using super (static binding).
2nd question: Why exactly do overloaded methods use static binding since they are virtual and can be overridden in subclasses?
Answer: There is no such thing that overloaded methods are statically binded.
Explanation:
class Sample{
public void method1(){
System.out.println("hello from A");
}
public void method1(String user){
System.out.println("hello "+user+" from overloaded method");
}
public static void main(String []argh){
Sample s = new Sample();
s.method1();
s.method1("name");
}
}
In the above code, the method method1() is overloaded but since it is neither static,final nor private, so it generates invokevirtual instruction, which means it is dynamically binded not static.
To clear the difference of binding and Dispatching refer this Question
If a subclass implements a instance method which has the same signature with its superclass, it is called override.
Comparatively if "override" a static method of its superclass, it is called hiding.
What is the difference between these two concepts in memory during function call ?
Overriding is a run-time phenomenon which depends on object and objects are created at run time so function call will be decided based on object at run time.
Whereas Static method calling is done by adding a class name like
MyClass.abc();
This does not depends on object as you are clearly mentioning the class name at compile time which has nothing to do with object because this static method is global to all object. So whatever class name you will mention that method will be called in case of the static method.
Addresses of static methods are determined at compile time. So there is no need to search further for the method address, it's decided way before.
Overridden method addresses are determined at run time. It depends on the instance and the address of the method is searched from base method to overridden method.
I have a super class with a final method
public final void foo(){ ... }
No you cannot do it.
Overriding a method in subclass with its superclass method marked final is not possible
. You can add a method with different signature
The purpose of final keyword applied to a method is that it doesn't allow subclass method to override it.
The main purpose of final is to prevent from overriding.So, you can not override final methods.
Still you can overload final methods.
You can't override the final super method.but you can overload it.
Make a method final only if it has an implementation that should not be changed and it is critical to the consistent state of the object.
You can't. The final keyword is there to prevent this.
See final methods in Java on Wikipedia.
It’s not clear why you have to have the same name. Either it’s intended to be a different method, then it can have a different name without problems or you are trying to do some sort of overriding you claimed not to do.
If your subclass needs an interface implementation which interferes with that method consider an inner class for that interface implementation.
Otherwise a method in the subclass does not override a superclass method with the same name if either:
it has different parameter types
the superclass method is private
the superclass method is package-private and the subclass resides in a different package
Please refer to the Java code below:
class Base{
Base(){
System.out.println("Base Constructor");
method();
}
void method(){}
}
class Derived extends Base{
int var = 2;
Derived(){
System.out.println("Derived Constructor");
}
#Override
void method(){
System.out.println("var = "+var);
}
}
class Test2{
public static void main(String[] args) {
Derived b = new Derived();
}
}
The output seen is:
Base Constructor
var = 0
Derived Constructor
I think var = 0 occurs because Derived object is half initialized; similar to what Jon Skeet says here
My questions are:
Why does the overridden method get called if the Derived class object isn't created yet?
At what point in time is var assigned value 0?
Are there any use cases where such behavior is desired?
The Derived object has been created - it's just that the constructor hasn't been run yet. The type of an object never changes in Java after the instant it is created, which happens before all constructors run.
var is assigned the default value of 0 as part of the process of creating an object, before constructors are run. Basically, the type reference gets set and the rest of the memory representing the object gets wiped to zero (conceptually, anyway - it may already have been wiped to zero before, as part of garbage collection)
This behaviour at least leads to consistency, but it can be a pain. In terms of consistency, suppose you had a read-only subclass of a mutable base class. The base class may have an isMutable() property which was effectively defaulted to true - but the subclass overrode it to always return false. It would be odd for the object to be mutable before the subclass constructor ran, but immutable afterwards. On the other hand, it's definitely strange in situations where you end up running code in a class before the constructor for that class has run :(
A few guidelines:
Try not to do much work in a constructor. One way of avoiding this is to do work in a static method, and then make the final part of the static method a constructor call which simply sets fields. Of course, this means you won't get the benefits of polymorphism while you're doing the work - but doing so in a constructor call would be dangerous anyway.
Try very hard to avoid calls to non-final methods during a constructor - it's very likely to cause confusion. Document any method calls you really have to make very clearly, so that anyone overriding them knows that they will be called before initialization has finished.
If you have to call a method during construction, it's usually not then appropriate to call it afterwards. If that's the case, document it and attempt to indicate it in the name.
Try not to overuse inheritance in the first place - this is only going to become an issue when you've got a subclass deriving from a superclass other than Object :) Designing for inheritance is tricky.
Why does the overridden method get
called if the Derived class object
isn't created yet?
Derived class constructor implicitly calls the Base class constructor as the first statement. Base class constructor calls method() which invokes the overridden implemention in the Derived class because that is the class whose object is being created. method() in Derived class sees var as 0 at that point.
At what point in time is var assigned
value 0?
var is assigned the default value for int type i.e. 0 before the contructor of Derived class is invoked. It gets assigned the value of 2 after the implicit superclass contructor call has finished and before the statements in Derived class's constructor start executing.
Are there any use cases where such
behavior is desired?
It is generally a bad idea to use non-final non-private methods in the constructors/initializers of a non-final class. The reasons are evident in your code. If the object that is being created is a subclass instance, the methods may give unexpected results.
Note that this is different from C++, where the type does change while the object is being constructed, so that calling a virtual method from the base class constructors doesn't call the derived class's override. The same thing happens in reverse during destruction. So this can be a small trap for C++ programmers coming to Java.
There are some properties of the Java language specification that should be noted in order to explain this behavior:
A superclass' constructor is always implicitely/explicitely called before a subclass' constructor.
A method call from a constructor is just like any other method call; if the method is a non-final, then the call is a virtual call, meaning that the method implementation to invoke is the one associated with the runtime type of the object.
Prior to a constructor execution, all data members are automatically initialized with default values (0 for numeric primitives, null for objects, false for boolean).
The sequence of events is as follows:
An instance of the subclass is created
All data members are initialized with default values
The constructor being invoked immediately delegates control to the relevant superclass' constructor.
The super constructor initializes some/all of its own data members, and then calls a virtual method.
The method is overriden by the subclass, so the subclass implementation is invoked.
The method tries to use the subclass' data members, assuming they are already initialized, but this is not the case - the call stack hasn't returned to the subclass' constructor yet.
In short, whenever a constructor of a superclass invokes a non-final method, we have the potential risk of entering into this trap, therefore doing it is not recommended.
Note that there is no elegant solution if you insist on this pattern. Here are 2 complex and creative ones, both requiring thread synchronization(!):
http://www.javaspecialists.eu/archive/Issue086.html
http://www.javaspecialists.eu/archive/Issue086b.html
why we should not use static and abstract for a single method?
the static keyword is defined so that a method can be called by a class name rather then an object. that means the method has to have some sort of definition. but abstract means you do not have any details about what the method does, it is as it says **Abstract**. When you inherit or extend a class you can then define the method.
Think of an interface.
If you are asking about having a static method inside of an abstract class, that is a different story. An abstract class is essentially as mentioned an interface and contains just a template of say functions that you must later on implement by inheriting / extending the class. Once you extend that class the static method does not come along with it (that is by default unless the access modifier is public / protected).
A static method is not inherited. Therefore, making it abstract is a nonsense.
The abstract keyword means that child classes must override the method - this is (one of the ways) Java supports polymorphism. If you want to make it so that subclasses cannot override the method you mark it final. So it would be impossible to have an "abstract final" method since they are the exact opposite of each other.
the static keyword implies final as well - all static method are also final. Thus it is impossible to have a method that is both static and abstract since you would be able to make a method that is abstract and final.
The reason for static being final is that it is bound to the class instead of the instance. That means that the compiler looks it up at compile time rather than runtime to determine which method to call. The reason what it is like that? Arbitrary decision that the designers of Java made - they could have allowed static method to be overridden but decided not to. I don't have any particular insight as to why the chose one over the other unfortunately.
As others have said, static+abstract is nonsense in Java. But there have been (rare) occasions where I've wished I could do just that.
The result I was looking for was basically to say that... "all concrete classes that extent this abstract class (or implement this interface) must provide a static method with this signature." This capability would allow these classes to provide meta-information about themselves.
Normally I have ended up with an instance method in these cases. If you stipulate that concrete implementations must support the default (no-arg) constructior, you can do...
MyInterface obj = MyClassThatImplementsMyInterface.newInstance();
obj.invokeTheMethodIWishWasBothStaticAndAbstract();