Instance and Static control-flow with inheritance and overriding/method-hiding - java

I'm toying around with instance control flow and static control flow, notice the code below
class A {
{
m1();
}
A(){
System.out.println("A constructor");
}
void m1(){
System.out.println("A m1");
}
}
public class Main extends A {
public static void main(String[] args) throws Exception {
Main m = new Main();
}
void m1(){
System.out.println("Main m1");
}
}
The output for the code is:
Main m1
A constructor
I know this is because:
First, static blocks and variables were identified top-to-bottom parent-to-child, in this case there was just a main() that was static. Second, the static blocks and variable assignments are executed, so main()'s execution starts, and there is an attempt to create a new Main object.
So third, the instance blocks and variables of parent class will be identified. Then they will be executed top-bottom. (After that the constructor of the parent class will run, then the instance blocks and variables of child class will be identified, following which they will be executed top-bottom and finally the child class' constructor will execute).
So the instance block inside A, calls `m1()`. Then, A's constructor executes. Finally, control flow is returned to `main()` and program terminates.
Now, the call to `m1()` from A invoked `m1()` of `Main`. However, had I made both the `m1()` methods static, everything else remaining same, the call to `m1()` from the instance block of A would then have invoked `m1()` of A.
I have two questions(Why? Purely for academic reasons, I'm still learning Java):
When both the m1() methods are non-static, is it possible to invoke A's m1() from the instance block of A? I tried doing a this.m1() but that still invoked Main's m1().(Why?)
When both the m1() methods are static, is it possible to invoke Main's m1() from the instance block of A? (I'm guessing no but I'm not certain).
I know in the first case, it's overriding taking place, and in the second case it's method hiding. But I'm still not sure how to answer my questions based on that knowledge.

After compilation is done java 8 compiler your code looks like this:
class A {
A() {
this.m1(); // at runtime this refers to Main class instance
System.out.println("A constructor");
}
void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() { }
public static void main(String[] args) throws Exception {
Main m = new Main();
m.m1();
}
void m1() {
System.out.println("Main m1");
}
}
Now to answer your first question: No. You cannot unless you are creating an instance of A(actual object of A).
To your second question:
after making both m1's static compilation looks like this:
class A {
A() {
m1(); // resolves to A's m1
System.out.println("A constructor");
}
static void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() {
}
public static void main(String[] args) throws Exception {
new Main();
}
static void m1() {
System.out.println("Main m1");
}
}
Now no matter which instance(A or Main) you create you will see A's m1 excuted.

1.(When two methods are instance method) If you are inside the A (parent) class, if you call m1(); or this.m1(); you will call the A version of the m1() method but if you are inside the main class (child), if you call m1(); you will call the main version of m1 although if you call super.m1(); you will be calling the A version of m1 method.
2.(If the methods are static) you can call each version wherever you want, without and object of a class, for example, you can invoke mainĀ“s m1 method inside the A block with the following line Main.m1(); // ClassName.StaticMethodName();

Related

Please explain the execution sequence of my program [duplicate]

This question already has answers here:
Java order of Initialization and Instantiation
(2 answers)
java "void" and "non void" constructor
(5 answers)
Closed 3 years ago.
I'm trying to understand the call sequence for my code. Someone, please explain the call sequence.
public class MainWithStaticCalls
{
static
{
String[] str = {"1", "2"};
System.out.println("Static");
main(str);
}
{
System.out.println("Init block");
}
void MainWithStaticCalls()
{
System.out.println("constructor");
}
public static void main(String[] a)
{
MainWithStaticCalls obj = new MainWithStaticCalls();
NewClass nc = new NewClass();
nc.callMe();
System.out.println("Main");
}
}
class NewClass
{
public void callMe()
{
System.out.println("I'm called");
}
}
As per my understanding, the static block will get executed as soon as the JVM starts its execution, even before main class. and instance init block gets executed after that. then constructor should get executed. But how the call back works if we call the main method from the static field. and which main will gets executed first, the one which JVM executes normally or the one which static field has called explicitly.
My output:
Static
Init block
I'm called
Main
Init block
I'm called
Main
P.S: I have modified my question. Earlier I confused the normal method with a Constructor so a few answers may look irrelevant, but that indeed helped me in understanding the problem.
I'll try to explain the calling sequence with an example, but first of all let's consider that if you add the void access qualifier, this will be a method and not a constructor.
Secondly remember that a class can have two type of initialization block:
Static Initialization Block
Instance Initialization Block
The Static Initialization Block will be called first of all and before the constructor, since is at class level and will be execute even before any class instance (i.e. object of that class type) is created. The second, i.e. the Instance Initialization Block is executed as soon as a new instance of the class is created. After that two blocks, it will be called the constructor. You can see it with the following example:
public class MainWithStaticCalls {
{
System.out.println("Init block called");
}
static {
String[] str = {"1", "2"};
System.out.println("Static called");
}
public MainWithStaticCalls() {
System.out.println("this is constructor");
}
void MainWithStaticCalls() {
System.out.println("this is NOT constructor");
}
public static void nope() {
System.out.println("Nope");
}
public static void main(String[] a) {
MainWithStaticCalls.nope();
System.out.println("************");
MainWithStaticCalls obj = new MainWithStaticCalls();
NewClass nc = new NewClass();
nc.callMe();
System.out.println("Main");
}
}
The output is:
Static called
************
Init block called
this is constructor
NewClass: I'm called
Main
If I comment out the "nope" static call:
public class MainWithStaticCalls {
... // Same thing as above
public static void main(String[] a) {
// MainWithStaticCalls.nope();
System.out.println("************");
MainWithStaticCalls obj = new MainWithStaticCalls();
NewClass nc = new NewClass();
nc.callMe();
System.out.println("Main");
}
}
The result is:
Static called
************
Init block called
this is constructor
NewClass: I'm called
Main
So it is the same result if do not comment out the "nope" call. This is to show that the static method is called only once, when the class is firstly faced by the JVM. If we instantiate another object:
public class MainWithStaticCalls {
... // Same thing as above
public static void main(String[] a) {
// MainWithStaticCalls.nope();
System.out.println("************");
MainWithStaticCalls obj1 = new MainWithStaticCalls();
MainWithStaticCalls obj2 = new MainWithStaticCalls();
NewClass nc = new NewClass();
nc.callMe();
System.out.println("Main");
}
}
The output is:
Static called
************
Init block called
this is constructor
Init block called
this is constructor
NewClass: I'm called
Main
you see that the Instance Initialization Block is called every time a new object fof that class type is created (as well as the constructor), while the Static Initialization Block is called only once.
There is no constructor defined in class, so default constructor gets called.
void MainWithStaticCalls()
is not a constructor. This is method, as constructor don't have return type.
void MainWithStaticCalls() is a method not a constructor.
Change it to,
public MainWithStaticCalls()
{
System.out.println("constructor");
}
There are rules defined for the constructor.
Constructor name must be the same as its class name
A Constructor must have no explicit return type
A Java constructor cannot be abstract, static, final, and synchronized
In Java, the constructor is not a method. It only has the name of the class and a specific visibility. If it declares that returns something, then it is not a constructor, not even if it declares that returns a void.
As others have already mentioned you confused constructor with method. Remove 'void' to make it a constructor again. Just for reference - this is how constructor described in the oracle docs: https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html

In java constructor and main which one will execute first?

Basically which one will execute first the main method or the constructor?
public class ConstructorExp {
public ConstructorExp() {
System.out.println("Ctt");
}
public static void main(String[] args) {
System.out.println("Inside Main Methos");
System.out.println("Main");
}
}
The main method will always be excecuted first, because it is a special static method that will be called from Java itself to start an application.
For more about the main method please read Java main() Method Explained for example.
Constructors will be created on object creation - in your case no object creation happens - so the constructor will never be executed.
You could modify your example to also execute the constructor:
public class ConstructorExp {
public ConstructorExp() {
System.out.println("Ctt");
}
public static void main(String[] args) {
System.out.println("Inside Main Methos");
ConstructorExp example = new ConstructorExp();
System.out.println("Main");
}
}
Be carefully, because the example object is never used the constructor call might be eliminated by some kind of optimization depending on the compiler you are using.

how to call Parent overridden method through object

How to call parent overridden method. Because when I call same method, overridden method of child class is called. But what if i want to call parent method explicitly through object, how can i do it? I want "hello B" as output.
class B
{
B()
{
System.out.println("B");
}
void display()
{
System.out.println("hello B");
}
}
class A extends B
{
A()
{
System.out.println("A");
}
void display()
{
System.out.println("hello A");
}
public static void main(String[] args)
{
A a= new A();
a.display();
}
}
output:
B
A
hello A
expected:
B
A
hello B
The instance you created is an A instance. Wherever A has an implementation for a method like display(), that one (A.display() ) will be called and get control. Always.
A.display() can decide that it'll use the parent's implementation by calling super.display() somewhere in its body. You can't do it from outside, only the A.display() method itself can do so.
When you design a class, you decide how its instances will react to method calls. If you override a method, you have a reason to do so: with a child instance, the parent implementation won't do what the method name demands. So, were it possible to call the parent method from outside, things would generally go wrong.
Try like this:
public class A extends B {
public A() {
System.out.println("A");
}
void display() {
System.out.println("hello A");
}
void displayB() {
super.display();
}
public static void main(String[] args) {
//first it will go to A constructor
//from A, constructor first it will execute the super();
//due to inheritance concept, execute B block statements //print "B"
//then it will execute the A block statements //print "A"
//after that it will execute the method, which will print the parent class method
new A().displayB();
}
}

ambiguity in invoking a method inherited from another class

I have two java class files
Hi.java which belongs to second package
package second;
public class Hi {
protected int v=20;
protected void m(){
System.out.println("i am protectTED");
}
}
S.java which belong to first package
package first;
import second.Hi;
interface i1
{
void m();
int a=200;
}
interface i2{
void m1();
int b=100;
}
class S extends Hi implements i1,i2
{
int a=50;
public void m()
{
System.out.println("hi");
}
public void m1()
{
System.out.println("hello");
}
public static void main(String[] args) {
S s=new S();
/*need correction here (i don't know the exact syntax to mention to get
the desired output)
s.m(); //should invoke method m() from class Hi only.
s.m(); //Should invoke method m() from class S only.
*/
//the following statements prints the desired values
s.m1();
System.out.println(s.v);
System.out.println(i1.a);
System.out.println(s.a);
System.out.println(b);
}
}
when i run the S.java class file method m() in class Hi should be invoked.("my intention") instead method m() of the same class i.e., class S is being invoked.
How to differentiate the 2 methods for invoking. Is it even possible?
when i run the S.java class file method m() in class Hi should be invoked.("my intention") instead method m() of the same class i.e., class S is being invoked.
Correct, because you've overridden it with m in S. Overriding methods is fundamentally different from overriding fields. (And in general, it's best to avoid overriding any fields that are visible to your subclass, as you're doing with a.)
In instance code in S, you can run the inherited m via super: super.m(). But you cannot do that from static code, not even static code in S. You could give yourself a private callSuperM in S:
private void callSuperM() {
super.m();
}
...and then use that in main:
s.callSuperM(); // "i am protectTED"
s.m(); // "hi"

Objects of multiple class in java

I was revising some of the old school concepts of Java in order to solve one problem . I have written the following code where i am trying the create objects of multiple class in that same classes and calling the methods with those objects from the main.
class a {
public void display() {
System.out.println("inside class a");
a a1= new a();
}
}
class b {
public void display() {
System.out.println("inside class b");
b b1= new b();
}
}
public class one {
void display() {
System.out.println("inside class one");
}
public static void main(String[] args) {
one o = new one();
a1.display();
b1.display();
o.display();
}
}
I am getting object cannot be resolved error. My question is what i need to change to let the above code work. And, do i need to always declare objects inside the main().
Any help will be highly appreciated
I'm not really sure why you would want to do that, but assuming you're just wondering about the possibility to implement such a thing - yes, it can be done.
You can create an instance of a class inside that same class, like so:
public class A {
public static A instance = new A();
public void display() {
System.out.println("inside class A");
}
}
Pay attention to the static modifier in the above code; it allows you now to access instance from another place (class, method, main) like so:
A.instance.display();
If you want to know whether you can declare a variable inside a method, and not a class, and make it accessible from another method, then the answer is - no, you cannot.
Yes you need to declare objects inside the main()
class a {
public void display() {
System.out.println("inside class a");
}
}
class b {
public void display() {
System.out.println("inside class b");
}
}
public class one {
void display() {
System.out.println("inside class one");
}
public static void main(String[] args) {
a a1= new a();
b b1= new b();
one o = new one();
a1.display();
b1.display();
o.display();
}
}
Don't know what you want to achieve and yes you should create object of class a and class b inside main functions to use instance methods of these classes.
package com.stack.overflow;
class a
{
public void display()
{
System.out.println("inside class a");
//a a1= new a(); ---> No need of this line as you can
// directly access instance variables and methods directly without
// creating any object or you can also use **this** keyword for the same
}
}
class b
{
public void display()
{
System.out.println("inside class b");
//b b1= new b(); ---> No need of this line as you can
// directly access instance variables and methods directly without
// creating any object or you can also use **this** keyword for the same
}
}
public class one
{
void display()
{
System.out.println("inside class one");
}
public static void main(String[] args) {
one o = new one();
a a1=new a();
b b1=new b();
a1.display();
b1.display();
o.display();
}
}
You may find the answer to your confusion easily - #ratul-sharker : a1 & b1 must be declared and instantiated inside the main. as well as other answers here correcting your code.
The real question is your notion of scoping and lifetime of variables - Not only a1 and b1 lie inside the classes a and b but they have been instantiated inside methods so they are local. So, try to understand the difference between field variables and local variables - their lifetimes and scopes are vastly different.
Accessing a local variable directly like that(which will be instantiated when the method is called) is like asking asking for a result from future in the present. Note that field variables will remain as long as object is alive but the local variables will remain only for the duration of the method call.
Hope it is clear to you now.
Also, your question:
My question was is it possible to create an object of an class in the
same class and call it from main?
Yes. Because main is a static method so it is not bound to an object like non-static method does. static methods are class level while non-static methods are object level. You can also create an instance in a non-static method for that matter.

Categories