Why does the below code print "Main"?
public class Main
{
public static void method()
{
System.out.println("Main");
}
public static void main(String[] args)
{
Main m = new SubMain();
m.method();
}
}
class SubMain extends Main
{
public static void method()
{
System.out.println("SubMain");
}
}
At runtime, m is pointing to an instance of Submain, so it should conceptually print "SubMain".
Static methods are resolved on the compile-time type of the variable. m is of type Main, so the method in Main is called.
If you change it to SubMain m ..., then the method on SubMain will be called.
It is because static methods are not polymorphic. Moreover static method should be invoked not by object but using the class, i.e. Main.method() or SubMain.method().
When you are calling m.method() java actually calls Main.method() because m is of type Main.
If you want to enjoy polymorphism do not use static methods.
Eclipse gives me this sort of warning when I try to do this sort of thing:
The static method XXX() from the type XXX should be accessed in a static way
Static methods do not take part in inheritance. The variable is of type Main, so the compiler resolved your function call to Main.method().
For added fun, try setting m to null.
Java performs early binding for static methods, unlike instance methods which are dynamically bound.
Because your object variable is of type Main the call is bound to the superclass implementation at compile time.
A good explanation is available here.
static methods are statically binded with their class name because m is type of Main class
then after compilation it would look like as following
Main.method();
after compilation of your class
run the following command
javap -c Main
u can see the jvm assembly code for Main class
and u would see following
m.method //invoke static
invoke static ,invoke special tells that static binding
invoke special,invoke interface tells that dynamic binding
Related
So I was playing around in Java to understand the concept of polymorphism, and I wrote this:
public class Practice
{
public static void main(String[] args)
{
Parent p = new Child();
p.instanceMethod();
}
}
class Child extends Parent {
public void instanceMethod(){
System.out.println("child's instance method");
staticMethod();
}
public static void staticMethod() {
System.out.println("child's static method");
}
}
class Parent {
public void instanceMethod(){
System.out.println("parent's instance method");
staticMethod();
}
public static void staticMethod() {
System.out.println("parent's static method");
}
}
So the output of this is:
child's instance method
child's static method
Why is the the static method called upon from the child's class and not from it's static type, Parent's class?
Is it because, it is first called by the instance method in child's class, so at that point its type is already fully dynamic, aka child's type?
static methods don't 'do' polymorphism. At all.
non-static (i.e. instance) methods do. The signature of the method is bound entirely statically; the actual prospect of finding which method to actually run in the type hierarchy is done entirely dynamically (late binding).
For static methods, the entire thing is entirely static.
So, let's go through this code:
p.instanceMethod()
The expression p is of type Parent. The compiler looks at the signatures available in Parent and all its supertypes and determines that the full method signature that this invocation of instanceMethod() is attempting to invoke is void instanceMethod(). This call (Parent::instanceMethod()V in bytecode speak) is encoded in the emitted .class file.
At runtime, the system checks the actual runtime type of what the p expression resolves to (which is the new Child() you did earlier), and does dynamic dispatch. The public void instanceMethod() of Child, which clearly overrides the one from Parent, is selected and executed, therefore, "child's instance method" is printed.
staticMethod() in Child
Next, let's look at that staticMethod invoke: at compile time, javac determines that this is clearly a reference to the staticMethod() that's right there, in Child. It encodes, in the bytecode an INVOKESTATIC bytecode to Child::staticMethod()V. Dynamic dispatch is not now or ever applied to static method calls.
At runtime.. that method is called.
Simple as that.
Perhaps you expected that a static method still first checks the call context but that's not how java works.
Why does the below code print "Main"?
public class Main
{
public static void method()
{
System.out.println("Main");
}
public static void main(String[] args)
{
Main m = new SubMain();
m.method();
}
}
class SubMain extends Main
{
public static void method()
{
System.out.println("SubMain");
}
}
At runtime, m is pointing to an instance of Submain, so it should conceptually print "SubMain".
Static methods are resolved on the compile-time type of the variable. m is of type Main, so the method in Main is called.
If you change it to SubMain m ..., then the method on SubMain will be called.
It is because static methods are not polymorphic. Moreover static method should be invoked not by object but using the class, i.e. Main.method() or SubMain.method().
When you are calling m.method() java actually calls Main.method() because m is of type Main.
If you want to enjoy polymorphism do not use static methods.
Eclipse gives me this sort of warning when I try to do this sort of thing:
The static method XXX() from the type XXX should be accessed in a static way
Static methods do not take part in inheritance. The variable is of type Main, so the compiler resolved your function call to Main.method().
For added fun, try setting m to null.
Java performs early binding for static methods, unlike instance methods which are dynamically bound.
Because your object variable is of type Main the call is bound to the superclass implementation at compile time.
A good explanation is available here.
static methods are statically binded with their class name because m is type of Main class
then after compilation it would look like as following
Main.method();
after compilation of your class
run the following command
javap -c Main
u can see the jvm assembly code for Main class
and u would see following
m.method //invoke static
invoke static ,invoke special tells that static binding
invoke special,invoke interface tells that dynamic binding
Ok just for sake knowledge , I tried below cases (Assume that Class A and B are in same package)
ClassA
public class ClassA {
public static void main(String[] args) {
System.out.println("A");
}
}
ClassB
public class ClassB extends ClassA {
public static void main(String[] args) {
System.out.println("B");
}
}
executing above ClassB it will produce output of B now after below change in classB
ClassB
public class ClassB extends ClassA {
//blank body
}
If I compile and run in terminal it gives me output A that was totally surprising as it should had given NoSuchMethodError as no main method was their so kindly explain the weird behavior ?
Note: Many answers contains Override word please use hiding as we cannot override static methods in java.
In the first case, you're hiding the main method since you're defining a new one in the subclass, in the second case you didn't you'll inherent A's main.
See The Java™ Tutorials - Overriding and Hiding:
If a subclass defines a static method with the same signature as a
static method in the superclass, then the method in the subclass hides the one in the superclass.
In Java subclasses inherit all methods of their base classes, including their static methods.
Defining an instance method in the subclass with the matching name and parameters of a method in the superclass is an override. Doing the same thing for static methods hides the method of the superclass.
Hiding does not mean that the method disappears, though: both methods remain callable with the appropriate syntax. In your first example everything is clear: both A and B have their own main; calling A.main() prints A, while calling B.main() prints B.
In your second example, calling B.main() is also allowed. Since main is inherited from A, the result is printing A.
public static void main(String[] args) is just a method which you inherit from A in second case.
THis is my superclass:
class Superclass {
int a=89;
final static void m( int p){
System.out.println("Inside superclass");
}
static void n(){
system.out.print("superclass");
}
}
This is my subclass::
class Subclass extends Superclass {
int a=90;
static void m( int p){
System.out.println("Inside subclass");
}
static void n(){
system.out.print("subclass");
}
}
Main class:
class main {
public static void main(String[] args) {
Subclass.m(89);
new Subclass().n();
}
}
the problem is that i cannot understand why Javac is giving me overriding error in static method..an P.S plzz elaborate that all rules for overriding are also valid for hiding. like
The new method definition must have the same method signature (i.e.,
method name and parameters) and the same return type. Whether
parameters in the overriding method should be final is at the
discretion of the subclass method's signature does not encompass the
final modifier of parameters, only their types and order.
The new
method definition cannot narrow the accessibility of the method, but
it can widen it The new method definition can only specify all or
none, or a subset of the exception classes (including their
subclasses) specified in the throws clause of the overridden method in
the superclass
my error is:
run:
Exception in thread "main" java.lang.RuntimeException: Uncompilable
source code - m(int) in javaapplication3.Subclass cannot override
m(int) in javaapplication3.Superclass overridden method is
static,final at javaapplication3.Subclass.m(JavaApplication3.java:18)
at javaapplication3.min.main(JavaApplication3.java:25) Java Result: 1
also i want to ask if static members called from classname to resolve whicch version of method is executed when method is hidden by subclass extending the superclass
what if i make anonymous object and then call method then how the compiler determines which version of method should be called.
in above code in main class i type this: new Subclass().n();
how does the compiler know subclass version of method should be called even if i am not providing the type of reference variable
From the JLS 8.4.3.3:
A method can be declared final to prevent subclasses from overriding or hiding it.
Static methods with the same signature from the parent class are hidden when called from an instance of the subclass. However, you can't override/hide final methods.
The keyword final will disable the method from being hidden. So they cannot be hidden and an attempt to do so will result in a compiler error. There is a nice explanation on this on Javaranch.
What you are observing here is in accordance with JLS 8.4.3.3 which states that:
It is a compile-time error to attempt to override or hide a final
method.
You are trying to override final static void m method in subclass , which is not permitted by Java compiler.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can we override static method in Java?
We cannot override the static methods of the base class.
Actually I tried something like this:
// Base class
public class StaticExampleImpl {
protected String name="overriding";
public static void display(){
System.out.println("static method display : base class");
}
}
Then the derived class is as follows:
//derived class
public class StaticDemo extends StaticExampleImpl {
// cannot override the static methods...
//#Override
public static void display(){
System.out.println("child!!! static method display");
}
public static void main(String[] args) {
StaticDemo d=new StaticDemo();
d.display(); // derived class display is called rather than Base class.
}
}
So, when I uncomment the #Override method, it gives error as "Static methods cannot be overriden". But with commenting it works fine. So, when we create the Objects and call the static methods with the instances, those work fine. so what is the difference??
because static methods are not get inherited.
When you uncomment #Override it means you are trying to override the
static method which is not possible thats why you are getting an
error.
But when you comment //#Override it means you are declaring a new
method in child class.
Static methods does not belong to an instance of a class, it belongs to the actual class.
When you call d.display();, you are really calling the static method of the StaticDemo d reference's static method.
if you did :
StaticExampleImpl d2 = new StaticDemo();d2.display(), you will find that it calls the base class's display.
However, don't do this. It leads to confusing code, and is a bad way to implement inheritance poorly.
Overriding depends the an instance of a class. polymorphismis that you can subclass a class and the objects implementing those subclasses will have different behaviors for those method defined in the superclass (and overridden in the subclasses) .static methods does not belong to an instance of a class so the concept is not applicable.
Static methods cannot be inherited. If you want to call the 'base' class static method, you have to explicitely call StaticExampleImpl.display().
Static methods are bound to class they can't be inherited thats why you can't have base class static method in derived class.
If you are trying to override a static method, there is probably something wrong with your design.
OOP and Polymorphism allows you to do the following:
public class MyClass1 {
public String toString() { return "MyClass1 Instance"; }
}
public class MyClass2 extends MyClass1 {
#Override
public String toString() { return "MyClass1 Instance"; }
}
public void printSomething(MyClass1 myclass1){
System.out.println(myclass1);
}
Inside printSomething, the toString method which is going to be called is the one on the runtime type of myClass1: when you pass inside printSomething an instance of MyClass2, its compile-type will be MyClass1 but its runtime type will be MyClass2
It is clear that to use polymorphism you need objects instances, where the actual runtime type could different from the compile type. Static methods however do not belong to any object instance, but to the class. Why don't you explain us what you are trying to achieve?
The following code:
StaticExampleImpl one = new StaticExampleImpl();
StaticDemo two = new StaticDemo();
StaticExampleImpl three = two;
one.display();
two.display();
three.display();
Will yield the following output:
static method display : base class
child!!! static method display
static method display : base class
As you can see, the method does not get inherited. This is why they are called 'static methods': they are called statically, not dynamically, as instance methods would be. The compile-time type of the class is what matters when calling static methods, not the runtime type.
This is also why you shouldn't call static methods through object instances. Always call them like this:
StaticExampleImpl.display();
StaticDemo.display();
This completely takes away the confusion that might (will) come up when people expect inheritance to work for these methods.
any static block in java, may be static variables, methods are loaded when the class is loaded. You probably know about class loader in java. So thing is static block (methods, variables or anything is static) is loaded once. So you can’t actually override any static block.
Commenting #Override means that you are writing another static method in sub class, but not just overriding base class method.