I have written the following code and created object for the super class.
class SuperClass{
static int a=2;
static int b(){
return 2;
}
int c(){
return 2;
}
SuperClass(){
System.out.println("Super");
}
static {
System.out.println("super");
}
}
public class Sub extends SuperClass{
Sub(){
System.out.println("Sub");
}
static {
System.out.println("sub");
}
static int b(){
return 3;
}
int c(){
return 3;
}
public static void main(String ax[]){
SuperClass f =new SuperClass();
System.out.println(f.c());
System.out.print(SuperClass.b());
}
}
When I checked the output, it is as follows:
super
sub
Super
2
2
I know that static block is executed only when object of the class is initialized or any static reference is made. But here, i did not make any of these to Sub class. then why do i see "sub" i.e. sub class' static block output?
I know that static block is executed only when object of the class is initialized or any static reference is made. But here, i did not make any of these to Sub class.
Your code doesn't, but in order for that main to run, Sub has to be loaded. So the static initializer for it is run.
E.g., I'm assuming you ran it like this:
java Sub
The java tool has to load Sub to call Sub.main. That's the static reference (access, really) causing the static initializer to run. (If you ran it in an IDE, the IDE will do the java tool part, but the result is the same.)
So here's what happened:
java triggers load of Sub
JVM has to load SuperClass in order to load Sub
So we see their static initializers run, in order (SuperClass, then Sub):
super
sub
java tool calls main
Code in main calls new SuperClass:
Super
Code in main calls f.c()
2
Code in main calls SuperClass.b:
2
As Holger helpfully points out, this is covered by the JVM specification in §5.5 - Initialization and the related §5.2 - Java Virtual Machine Startup:
Initialization of a class or interface consists of executing its class or interface initialization method (§2.9).
A class or interface C may be initialized only as a result of:
...
If C is a class, the initialization of one of its subclasses.
If C is a class, its designation as the initial class at Java Virtual Machine startup (§5.2).
That second-to-last bullet point covers SuperClass, and the last bullet point covers Sub.
Because your main() method is a member of Sub, that class needs to be loaded for your program to run.
In calling main, all the static initialisers are called, first in the super class, then the sub class.
That explains the output you observe.
static blocks are run when the class is loaded. usually that is because you call a constructor or static member. in this case, it is because you executed the main method (a static member).
side notes:
another edge case is calling Class.forName(className) to load a class.
you may also notice that the base class is loaded before the subclass.
Related
I have created anonymous class by implementing interface I inside public static void main() method. So, by java 8 for the abstract method test(), the implementation is provided from imple() method of class C.
So, inside public static void main() method, printing _interface.getClass(), I got
package_path.Main$$Lambda$1/310656974 which is absolutely fine. Bacause it print's the anonymous class name.
Also, _interface is pointing to an anonymous object in heap and hence I'm doing _interface.test();
So, the first statement that test() method has now is to print the class name,
But eventually what it print was,
package_path.C (telling me C is the class name). How is that possible? Shouldn't package_path.Main$$Lambda$1/310656974 be printed again? Because 'this' means anonymous inside the test method right?
#java.lang.FunctionalInterface
interface I {
void test();
}
class C {
void imple() {
System.out.println(this.getClass());
System.out.println("Inside Implementation");
}
}
class Main {
public static void main(String[] args) {
I _interface = new C()::imple;
System.out.println(_interface.getClass());
_interface.test();
}
}
Hopefully, this might help you understand, that when you declare
I _interface = new C()::imple;
you've actually implemented the interface somewhat similar to (though not same as):
I _interface = new I() {
#Override
public void test() {
new C().imple(); // creating an instance of class `C` and calling its 'imple' method
}
};
Hence when the test method is called, it first creates an instance of C which prints
class x.y.z.C
as the class.
Because 'this' means anonymous inside the test method right?
Now as you can see above, there is no more anonymous class from which imple
is being called from, hence this is not representing the anonymous class anymore.
As Holger clarified in comments further, despite the representation as lambda or anonymous class at the calling site, the this.getClass() inside a method of class C will evaluate to C.class, regardless of how the caller looks like.
Recommend: Continue to read and follow on Is there any runtime benefit of using lambda expression in Java?
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 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.
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