This question already has answers here:
java constructor: this(.)
(3 answers)
Closed 6 years ago.
Why super have no effect on i field in class C ?
The output is 012, but why not 321, since class B extends class C ?
public class C {
protected int i;
public C(int i){
this(i,i);
System.out.print(this.i);
this.i=i;
}
public C(int i, int j) {
System.out.print(this.i);
this.i=i+j;
}
public C(){
this(1);
System.out.print(i);
}
public static void main(String[] args) {
C c=new C();
}
}
public class B extends C{
public B(){
super.i=3;
}
public static void main(String[] args){
C c=new B();
}
}
super.i just refers to this.i (or simply i) because class B does not declare its own version of i, so it inherits the field from C already.
public B(){
super.i=3; // the super here does not do anything
}
The first thing a constructor needs to do is invoke one of the super constructors. So this is equivalent to:
public B(){
super();
i=3;
}
As you can see, the code in the superclass C is executed before i is set to 3. That's why it prints the old value.
super can be used for accessing overridden methods. In your scenario i is an inherited member of B.
If you override a method in B that was defined in C, you can call it from B by using the super keyword.
It´s quite simple. That´s what is happening:
B Constructor is called.
B doesn´t have an explicit super constructor call- so implicity call super().
C() Constructor is called -> call C(int)
C(int) Constructor is called -> call C(int,int);
C(int, int) is called. print i. i only has the default value yet so print ->0
C(int, int) does increment i by j, which at this point is 1+1 = 2
C(int) Constructor callback, as C(int, int) is done, print i = 2
C(int) sets i = 1 and prints i = 1.
B() callback as C() is done. set instance variable i to 3.
As you can see you have a different output as 021 and that´s everyone that does happen.
I don´t know what your initial intention was, but super can have different meanings.
In the constructor you usually access a parents constructor with super.
by doing super.i you are only accessing the instance variable i of the parent class.
you could, by doing super.testMethod() call an method testMethod from the parentclass
Related
This question already has answers here:
Are fields initialized before constructor code is run in Java?
(5 answers)
Closed 2 years ago.
I'm trying to understand why the output of the following Java code is as like this:
class A {
public A() {
System.out.print("A()");
}
public static void main(String[] args) {
}
}
class B {
public B() {
System.out.print("B()");
}
public static void main(String[] args) {}
}
class C extends A {
B b = new B();
}
public class E05SimpleInheritance {
public static void main(String args[]) {
new C();
}
}
Output:
"A()B()"
I would imagine that when the main method of the E05SimpleInheritance public class is called the following things should happen
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
Since its member 'b' is an object of class B, class B is loaded in memory
Since we construct an object of Class B its constructor is called which should print B()
Default constructor of C is called which automatically calls the constructor of the superclass A which print A()
So the final output should be B()A() which is obviously wrong so I do not really understand how the code flows in this case. Can you perhaps show me why is A()B() printed instead of B()A()
Your mistake is in step 1:
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
This is not what’s happening. In reality, non-static fields are initialised at the beginning of the constructor, not before it. And the base class constructor is implicitly (or explicitly) invoked even before that.
In other words, javac generates code for C which is equivalent to the following:
class C extends A {
B b;
C() {
super();
b = new B();
}
}
I wrote down this mini-program:
A class:
public class A
{
public A()
{
System.out.println(getS());
}
public String getS() { return s;}
}
B class:
public class B extends A
{
private String s = "hello2";
public String getS() { return s;}
}
main:
public static void main(String[] args)
{
B b = new B();
}
and it printed:
null
Why is that?
I know that the String that printed is B's string, but why it didn't initialized before?
According to this answer - the variable initialized before the constructor..
EDIT -
I edited the code so the unrelated code won't confuse
Here is what's going on: when you construct B, the first thing its constructor needs to do is constructing A. This is done before B's own field s is initialized.
A constructs its own s, and then calls getS. However, it does not get its own getS, because B provides an override for it. Recall that B.s has not been initialized yet. That is why you see null printed.
Follow-up reading: What's wrong with overridable method calls in constructors?
What is happening:
You create a B instance, this will call the super() so the constructor of A.
Here it will do the print using the getter getS(). This will use the getter of B since this is the type of this but in this getter, the String is not yet instanciate since it is still doing the super class construction, so it return null.
Note that the String s in A is hidden by the one in B
The order during an instance is :
the static (from the super then the class)
the super class declaration (statement then constructor)
the block statement
the constructor
As Seen with :
public class A{
static{System.out.println("sA");}
{System.out.println("A1");}
public Main() {
System.out.println("new A");
}
{System.out.println("A2");}
public static void main(String[] args) {
new A();
}
}
class B extends Main {
static{System.out.println("sB");}
{ System.out.println("B1"); }
public B() {
System.out.println("new B");
}
{ System.out.println("B2"); }
}
Output :
sA
sB
A1
A2
new A
B1
B2
new B
it prints null because you have polymorphism in java. You Overrided method getS(). So when you call it from A, you try to call getS() from class B. But you didn't create instance of class B yet, because you need to finish class A first. So String in class B haven't been initialized yet, because of it you get null.
In this program
class a
{
int a=25;
public void aa()
{
System.out.println(a);
}
}
class b extends a
{
int a=2;
public static void main(String[] args) {
b x=new b();
x.aa();
}
}
why does "x.aa()" prints 25 ans why not 2?,what is the reason behind it?
class a
{
int a=25;
public void aa()
{
System.out.println(a);
b();
}
public void b()
{
System.out.println("this should print");
}
}
class b extends a
{
int a=2;
public static void main(String[] args) {
b x=new b();
x.aa();
}
public void b()
{
System.out.println("this should not print");
}
}
and if we consider the above output,then here again the output of b() of above should print "this should print" but we are getting the ouput from sublcass "this should not print"
Class b inherits class A, so when you call x.aa, it is calling method aa of class a. The member a of class a is initialized with 25 so it prints 25. Class a does not know about the member a of class b.
Fields cannot be overridden, and are not virtual. B.a* is independent of A.a, to the point that they can actually have different types. There is no way for B to make A aware of B.a in place of A.a. Instances of B will actually have two fields named a, but one is hidden ("shadowed") by the other. (If desired, code B can refer to its A.a field by writing ((A)this).a. This is because the appropriate a is selected based on the type of ((A)this), which is A, rather than the runtime type of the instance, which would be B or a subtype of B.)
* Note: I have renamed your classes to A and B: per the Java naming conventions, class-names begin with uppercase letters.
b x=new b();
while you will do this this will print out put of the constructor as its giving because its clearly making the object of b class and while in the case of class A in that class that b() act as the method so it wont call when you are making object of class b.
while in the case of
b x=new b();
x.aa();
this it will by default call the inheritance and will print as u getting output.
and one more thing.
public void aa()
{
System.out.println(a);
}
in the case of this it will use the local variable of that particular class so it will print whatever you have defined on that class. in your case that is a=25;
by the way nice question.
method aa() is member of class a. so, method aa() can see/access instance member of class a.
Now, you have inherited class a to b. it means object of class b can access/call aa(). but, it doesn't mean that aa() is allowed to access variable a of class b. thats why method aa() is printing the variable a of it's own class and prints 25.
now about your second program. in class b, you are overriding method b(). while calling an overridden method, the selection of method(whether from sub class or super class) is done on the basis of instance of a invoking object(whether sub class or super class respectively).
you have called method aa() with the instance of class b that is why method b() of class b is called.
Why overloading is not happening here even though passing integer argument to method "p" . ?
public class Test {
public static void main(String[] args) {
B a = new A();
a.p(10);
a.p(10.0);
}
}
class B {
public void p(double i) {
System.out.println(i * 2);
}
}
class A extends B {
// This method the method in B
public void p( int i) {
System.out.println(i);
}
//added below code
public void p( double i) {
System.out.println(i*5);
}
}
Output:50.0
50.0
Because the variable a is declared as B, only the p method declared in B is visible and thus chosen. There's no overriding involved.
When in doubt, annotate your method with #Override in your favorite IDE. The IDE won't let it compile if it's not actually overriding anything.
After your edit, you now have an overriden method in the form of A#p(double). When you invoke
a.p(10);
a.p(10.0);
The method p visible on the B class will be invoked. Through polymorphism and because the variable a is of run time type A, the overriden method declared in A will be invoked.
Note that the int argument in
a.p(10);
becomes a double through widening primitive conversion.
Because you're invoking things through a reference-to-a-B. That only has one method.
It's always calling the method in B, because:
the variable is of type B, so the compiler only knows about the double method
the method in A does not override B's method because the parameter type int is different from B's double - it's invisible to the calling code
ot sure if a similar question do exists or have been answered earlier. I did a search but couldn't find anything related.
Please see following example. There's a class A with noargument contructor. Class B extends Class A but no default contructor exists. The output is B-> get c, and I think java uses the runtime polymorphism logic to invoke the B object method.
Here would like to understand if its correct and how Java works here (Maybe what's the underlying logic)
Thanks
public class A {
private String cStr="";
private String dStr="";
A()
{
getcStr();
}
public String getcStr() {
System.out.println("A-> get c");
return cStr;
}
public String getdStr() {
System.out.println("A-> get d");
getcStr();
return dStr;
}
}
public class B extends A{
private String cStr;
public String getcStr() {
System.out.println("B-> get c");
return cStr;
}
}
public static void main (String[] args)
{
A a= new B();
a.getdStr();
}
EDIT: the output for the a.getdStr() is A-> get d B-> get c
If a class doesn't have a default constructor, in your case B, then java will implicitly insert a no argument constructor something like this
public B() {
super();
}
To answer your question, Yes, due to run time polymorphism, Java invoke's B's getcStr() method. Because B's constructor is calling A's constructor via super()
This is a famous anti-pattern. And its anti-pattern because you are trying to invoke a overriden method on B before B is fully constructed
Imagine your B class was like this
public class B extends A{
private String cStr = "abc";
public String getcStr() {
System.out.println(cStr);
return cStr;
}
}
Now the output of your program would have been null instead of "abc" because B is not fully constructed yet (that means cStr is not initialized to "abc")
there is no default constructor for B so it'll call A() constructor.....
Now new B(); creates the object of B so java will first look into class B that is any procedure like getcstr() exists if procedure found there it will invoke it otherwise check in the super class for that procedure......