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.
Related
public class Test {
public static void main(String[] args) {
B b = new B();
b.test();
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
why the cant input out "b"?
i just think b.test() will call method of superClass, so b will user superClass's attribute.
why the cant input out "b"? i just think b.test() will call method of superClass, so b will user superClass's attribute.
Java class and instance variables can be inherited, but they are not virtual. That is, all variable identifiers appearing in Java code are resolved at compile time -- there is no dynamic resolution for them.
Thus, the appearance of identifier aString in method A.test() is resolved at compile time to the aString attribute of class A. This is the attribute that all invocations of that method will access, regardless of the actual class of the object on which it is invoked. If you want to use the attribute of class B when test() is invoked on an instance of that class then provide getter methods in classes A and B and have A.test() obtain the string via those.
The variable in b is hiding the variable in a. You can fix it by removing the type in b
class B extends A {
public B () {
aString = "b";
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
Creates 2 aString variables for B. While A will not know about B extending it, B can always access "things" from its parent class A, using the super keyword. So when you are in B, you can use aString and super.aString and they will refer the 2 different variables:
class Ideone {
public static void main (String[] args) {
A a=new A();
B b=new B();
a.test();
b.test();
b.suptest();
}
static class A {
String aString="A.aString set from A";
void test() {
System.out.println("A.test(): "+aString);
}
}
static class B extends A {
String aString="B.aString set from B";
{
super.aString="A.aString set from B";
}
void test() {
System.out.println("B.test(): "+aString);
}
void suptest() {
System.out.print("B.suptest() calling super.test(): ");
super.test();
}
}
}
You can try it on IdeOne, produces output
A.test(): A.aString set from A
B.test(): B.aString set from B
B.suptest() calling super.test(): A.test(): A.aString set from B
Where the first two lines show nothing fancy, A.aString and B.aString both contain their initial value.
But the third output line shows that super.test() call in B really "ends" in A.test(), and that the initializer block in B really altered the inherited aString field.
(Side note: the static class magic relates to the example being contained in a single file, it doesn't affect the inheritance-part)
You are correct.
Since Class A and the method test() are not abstract and the fact that the method test() was not overrided by its subClass B, the return will be exactly how was specified in Class A even if you call it from a B instance.
I am facing a problem with the below program , it has two classes A and B and one method getObject() in Class A that has been overridden in class B, Class B extends Class A.
I am calling getObject() from the base class constructor which I believe it will call the overridden method in class B, and at runtime the error is null pointer exception, why the Object has not been initialized, even so it has?
class A {
Object object = new Object();
public A() {
System.out.println("A Class");
getObject();
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object();
public B() {
System.out.println("B Class");
}
#Override
public void getObject() {
System.out.println("Class B Version");
System.out.println(object.toString());
}
}
public class Init {
public static void main(String[] args) {
new B();
}
}
output
A Class
Exception in thread "main" Class B Version
java.lang.NullPointerException
at net.mindview.util.B.getObject(Init.java:28)
at net.mindview.util.A.<init>(Init.java:8)
at net.mindview.util.B.<init>(Init.java:21)
at net.mindview.util.Init.main(Init.java:34)
According to this answer:
The correct order of initialisation is:
Static variable initialisers and static initialisation blocks, in textual order, if the class hasn't been previously initialised.
The super() call in the constructor, whether explicit or implicit.
Instance variable initialisers and instance initialisation blocks, in textual order.
Remaining body of constructor after super().
See sections ยง2.17.5-6 of the Java Virtual Machine Specification.
So basically, object in class B is not initialized yet during constructor of class A is being executed (point 2: implicit super() call).
Within B constructor you call A construct which is using B's getObject() which is using not initialized object from B.
Use debugger step by step and you will see the flow.
The NPE is coming from the class itself, not object. While the constructor is working, this is null.
B extends A, so there's an implicit super constructor call inserted. That prints your "A Class" line, but then the method call is equivalent to this.getObject();, and this is null.
I think the key point of this problem is that you should know that the constructor of super class (A in case) will be called first. let's assume antoher condition that A also extends C , in case, constructor of c will be called first.
so the order of call should be : 1 construtor of C, 2 constructor A and then constructor of B at the last.
For your case, because Constructor A was called first , at this point object is not initialized yet which cause the null pointer excetion
Execution orders are:
class A {
Object object = new Object(); // --------------- 2
public A() {
System.out.println("A Class"); // ---------- 3
getObject(); // ---------------------------- 4 (calls B.getObject())
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object(); // --------------- 7 (not executed)
public B() {
System.out.println("B Class"); // ---------- 8 (not executed)
}
#Override
public void getObject() {
System.out.println("Class B Version"); // -- 5
System.out.println(object.toString()); // -- 6 (exception!)
}
}
public class Init {
public static void main(String[] args) {
new B(); // ------------------------------- 1
}
}
You should never call overridable method in constructors as it introduces ambiguity in terms of which method to call. In you case your super class A calls B's getObject(). At this Point B is yet not instantiated so the call fails and gives you NPE.
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......
Consider the following code classes.
public class A
{
public A()
{
callCreation();
}
protected void callCreation()
{
System.out.println("A Created!!");
}
}
public class B extends A
{
protected void callCreation()
{
System.out.println("B Created!!");
}
}
public class C extends B
{
protected void callCreation()
{
System.out.println("C Created!!");
}
public static void main(String[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}
The output of running the class C is given below.
A Created!!
B Created!!
C Created!!
The first output line in the output A Created!! is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?
The callCreation methods in B and C override the method from A. So when the method is called in the constructor A the implementations in B and C will be run, even though the constructors of B and C have not been executed yet. This is possible because constructors don't actually create the object, rather they are called to initialize some moments after the JVM has created it.
In general it's a very bad idea to call methods that can be overridden from a constructor for this very reason. A method in B or C may assume that the constructor and object initializers have already been run, and read an unexpected value from a field. For example the following ends up printing "B Created!! null" because the field still has not be assigned its value.
public class B extends A
{
final String msg = "Yes!";
protected void callCreation()
{
System.out.println("B Created!! "+msg);
}
}
thinking in this way makes it more obvious:
when an object of type B is being created super() keyword calls the A constructor,
then in A constructor "this.callCreation()" is executed, which refers to the current
object which is B, so callCreation corresponding to the current object(B) is called.
the same process is done for C.
public class A {
public A() {
this.callCreation();
}
protected void callCreation() {
System.out.println("A Created!!");
}
}
class B extends A {
public B() {
super();
}
protected void callCreation() {
System.out.println("B Created!!");
}
}
class C extends B {
public C() {
super();
}
protected void callCreation() {
System.out.println("C Created!!");
}
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
}
}
public class XXX {
#Test
public void test() {
B b = new B();
b.doY();
}
}
class A {
public void doY() {
XProcedure.doX(this);
}
}
class B extends A {
public void doY() {
super.doY();
XProcedure.doX(this);
}
}
class XProcedure {
public static void doX(A a) {
System.out.println("AAAA!");
}
public static void doX(B b) {
System.out.println("BBBB!");
}
}
The output is
AAAA!
BBBB!
And I wonder why?
Although XProcedure has two methods with the same name - doX, the two signatures are different. The first method gets an instance of class A as a parameter, and the second one gets an instance of class B.
When you call XProcedure.doX(this), the correct method is called according to the class of the passed parameter.
"AAAA!" is printed because of the super.doY() call.
"BBBB!" is printed because of the XProcedure.doX(this); call.
this differs in A's constructor from this in B's constructor for the reasons in Che's answer. Although A's contructor is called from within a B's constructor, in A's scope, the instance is of class A.
You called super.doY which is a method on B's superclass A.
All animals can talk.
A cat is an animal.
A cat talks and drinks milk.