**Java code-MySuper class is the parent class and is extended by MySub class.I am creating the object MySub mySub = new MySub().I thought the output would be "y" but when I tried to run the code it was showing null as an output **
class MySuper {
String strl = "x";
public MySuper() {
myMethod();
}
void myMethod() {
System.out.print(strl);
}
}
class MySub extends MySuper {
String str2 = "y";
void myMethod() {
System.out.print(str2);
}
public static void main(String[] args) {
MySub mySub = new MySub();
}
}
The implicit constructor used by MySub looks like this:
class MySub extends MySuper {
String str2;
MySub() {
super();
str2 = "y";
}
// rest omitted for brevity
}
While inline field initialization is technically moved into the constructor, that's not necessarily important to know in and of itself. The important part is that the super constructor is invoked before the subclass's fields are initialized. So, when the super constructor invokes the myMethod() method, which is overridden by the subclass, the str2 field has not yet been assigned a non-default value. This results in your code printing out null.
And this is why you should avoid invoking overridable methods in a constructor.
This is due to Java dynamic method dispatch.
In your example. when you're instancing with the default constructor a MySub instance, this implicitly performs a call to the superclass' constructor. Within the superclass' constructor there is a call to myMethod() which is declared in MySuper and overridden in MySub.
Now, even if myMethod is being called from the superclass' constructor, which could fool us into thinking that the superclass' version of myMethod is being called, this is not what is actually happening.
The instance that is performing all these calls is still a MySub instance; therefore the myMethod implementation that is being invoked by Java is the closest implementation to MySub, i.e. the myMethod overridden by MySub.
So, if in this case the myMethod version that is being invoked in the superclass' constructor is the one overridden by MySub, why it's not printing str2 value? This is because, although method calls are dynamically dispatched, fields are statically dispatched. In Java, only methods can override their base class' methods. Child class' fields can only shadow base class' fields (with the same name). So Java already knows at compile time which fields are being used and only at run time which method implementations are being invoked. This means that when you're using a field in a child class, you can be sure that the one you're using is always the one you're referring to.
Getting back to your example, since myMethod is being invoked from the superclass' constructor, at this point we're still initializing the parent object, the child class' fields have not been initialized yet, they still contain their default values (the default value for references is null). So, in your dynamically dispatched myMethod we are printing the value of the statically dispatched str2 which is still at null because the child class initialization has not happened yet.
Minor Mistakes:
null output is coming because of extending the MySuper class and extending MySuper class is not required because the default class object can be created anywhere in a package without extending that.
You have not called the method myMethod() after creating the object mySub.That's why it is not printing the output as y.
Solution:
Try the code below, it is working smoothly.
class MySuper {
String strl = "x";
public MySuper() {
myMethod();
}
void myMethod() {
System.out.print(strl);
}
}
// class MySub extends MySuper {
class MySub {
String str2 = "y";
void myMethod() {
System.out.print(str2);
}
public static void main(String[] args) {
MySub mySub = new MySub();
// extra line added
mySub.myMethod();
MySuper ms=new MySuper();
}
}
Related
I'm studying CS and we have questions about polymorphism that I cant wrap my mind around. Here is an example:
public class AA{
public AA(){
foo();
}
private void foo() {
System.out.print("AA::foo ");
goo();
}
public void goo(){
System.out.print("AA::goo ");
}
}
public class BB extends AA{
public BB(){
foo();
}
public void foo(){
System.out.print("BB:foo ");
}
public void goo(){
System.out.print("BB::goo ");
}
public static void main(String[] args){
// Code goes here
}
}
When in void main i add the line:
AA a = new BB();
it goes first AA constructor prints AA:foo but then goo() sends it to BB's goo, why so?
Simple polymorphism such as "Animal -> cat/spider/dog" is easy to understand but when it comes to this I'm just lost. Can you guys give me any tips how to read this code? What are the rules are?
EDIT: there is no #Override annotation because this is a question from an exam.
Explanation
public class AA {
private void foo() { ... }
^^^^^^^
}
Polymorphism is not applied to private methods. A subclass does not inherit private methods, so they cannot be overridden:
A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:
m is a member of the direct superclass of C.
m is public, protected, or declared with package access in the same package as C.
No method declared in C has a signature that is a subsignature of the signature of m.
Java Language Specification - 8.4.8. Inheritance, Overriding, and Hiding
Therefore, the foo() call from the A constructor doesn't invoke BB#foo, it calls AA#foo.
But the goo() call within AA#foo refers to the overridden method BB#goo. Here, with public methods, method overriding and polymorphism were applied.
It's a bit tricky, so I would recommend you put the #Override annotation everywhere it's supposed to be.
public class BB extends AA {
#Override // it doesn't compile - no overriding here
public void foo() { ... }
#Override // it does override
public void goo() { ... }
}
It also might be helpful to detect another problem:
Programmers occasionally overload a method declaration when they mean to override it, leading to subtle problems. The annotation type Override supports early detection of such problems.
If a method declaration in type T is annotated with #Override, but the method does not override from T a method declared in a supertype of T, or is not override-equivalent to a public method of Object, then a compile-time error occurs.
Java Language Specification - 9.6.4.4. #Override
Illustration
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation super();, an invocation of the constructor of its direct superclass that takes no arguments.
Java Language Specification - 8.8.7. Constructor Body
To put it simply,
public BB() {
foo();
}
turns into
public BB() {
super();
foo();
}
Keeping super(); in mind, we can make the next illustration:
new BB()
AA() // super(); -> AA constructor
A#foo() // private method call
B#goo() // polymorphic method call
BB() // BB constructor
B#foo() // plain method call
It's explained very well in the official docs:
https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
So, the Java compiler is adding super() without args for you.
In fact, if the class you are extending doesn't have a default constructor you will be required to call this constructor with args before.
Otherwise, the reason why AA:goo is not being called is because is override by BB even if it doesn't have the #Override annotation, if you want to see that call you need to use super(); in your b:goo method. In fact, the foo is not override because it private so it's not possible to override it, if you try to add the annotation #Override you'll se you have a compilation failure.
AA::foo() is private so AA::foo() and BB::foo() aren't the same.
new BB()
will call AA::Constructor first, calling AA::foo().
AA::foo() call goo() and since you instantiated BB class it'll be BB::goo().
Please use "override" keyword on method when you want to do something like this
There is also a serious design flaw in the example code: it is calling an overridable method from a constructor. This means that object BB might not be fully initialized at the time that this method is called on it. For example:
public class AA{
public AA(){
foo();
}
private void foo() {
System.out.print("AA::foo ");
goo();
}
public void goo(){
System.out.print("AA::goo ");
}
}
public class BB extends AA{
private Date timestamp;
public BB() {
super();
foo();
timestamp = new Date();
}
public void foo() {
System.out.print("BB:foo ");
}
public void goo() {
// goo() gets called before timestamp is initialized
// causing a NullPointerException
System.out.print("BB::goo " + timestamp.getYear());
}
public static void main(String[] args){
AA obj = new BB();
}
}
Remember this: NEVER CALL AN OVERRIDABLE METHOD FROM A CONSTRUCTOR (even not indirectly as in this example)
Polymorphism is Simple yet Confusing at times when we use different set of names [Which is the case here].
Polymorphism is basically a Parent Child Relationship. Key here is, if you are trying hard to place the names of the classes, use yourself instead i.e. give comment line next to class names as below
public class AA{} //your Parent name
public class BB extends AA{} // yourself i.e. your name
When it comes to the code like this, AA a = new BB(); , decode the code as below:
BB is you, AA is your parent.
new keyword is with YOU(i.e. BB), so a new object of YOU would be created or born. In order to for YOU to born, without your parents(i.e. AA), you cannot exist and so, first they will be born or created (i.e. AA constructor would run). Once your Parents (i.e. AA) are created, then it is time for YOU to born(i.e. BB constructor would run).
In your example,
public AA(){
foo(); -- line A
}
private void foo() {
System.out.print("AA::foo ");
goo(); -- line B
}
public void goo(){
System.out.print("AA::goo "); -- line C
}
As I told earlier, Line A would be called when you say AA a = new BB(); as Line A is in Constructor of AA, Line A calls foo() method and so the control lands in foo(), prints "AA::foo " and executes Line B. Line B calls goo() method and so on it reaches Line C. After Line C is executed, there is nothing left to execute in AA constructor (i.e. Object is created) and so the control flows down to the child Constructor ( As parent is created, it is time for the child to born) and so the child Constructor would be called next.
For Students/Beginners, I strongly recommend to go through Head First Java Edition. It really helps you in laying the Java Foundation Strong.
Please verify my understanding/guess, why code below throws NPE and what exactly happens:
After new Derived() constructor of Derived class called.
Derived contructor immediately calls Base constructor (implicit constructor chaining happens)
Base constructor calls foobar(). There is no different foobar() methods (Base version and Derived version), so this is foobar() in "version" as overridden in Derived.
This single foobar() "version" (shared between Base\Derived) searches for str field to work with. As foobar() is overridden ("defined") in Derived, it needs str from Derived (it cannot use str from Base).
At this moment str in Derived is not init (because until Base constructor finishes, Derived constructor cannot start working), so we get NPE.
P.S. I know that it is not recommended to call non-final or non-private, non-static methods from constructors. Besides, for virtual method in C++, its overridden version from Derived won't be called in Base contructor like in Java.
class Base {
String str = "abc";
Base() {
foobar();
}
void foobar() {
System.out.println(str.toUpperCase());
}
}
class Derived extends Base {
String str = "qwe";
Derived() {
foobar();
}
#Override
void foobar() {
System.out.println(str.toLowerCase());
}
}
public class My {
public static void main(String[] args) {
new Derived();
}
}
My own research shows that in those answers there was no same (shadowed) field variable (str), which adds to the confusion.
answer1
answer2
Can anybody explain me what is the reason for a sub class object is incapable of holding a super class constructor?
class Alpha
{
String getType1()
{
return "alpha";
}
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Here the output is "beta"; but object a1 doesnt have the visibility to acc()?
Nothing surprising here:
System.out.println(a1.getType1());
You are calling a method that is defined in the super class; and overridden in the a subclass. You create an instance of the subclass; and the method that gets executed ... is the overridden version.
The fact that Beta contains another method which is not at all used in your example anyway doesn't come into play here at all. And even if getType1() would be calling acc() - that would still work. That is the essence of of polymorphism!
And just to be precise: none of the methods you have in your classes is a constructor!
i just found the answer here we need to know that when we create beta() internally it will call all its super class default constructors hence the JVM knows that there is more than one existing class but when i declare and initialze like:
Alpha a1=new Beta();
eventhough the JVM knows that beta class is existing but your restricting your access of a1 by saying it is of the type Alpha class hence it cannot access your subclass methods.
When you create a object of child class making reference to its parent class as you did, you only have visible to those methods which belongs to the parent class. but if you want to call the child method using reference of parent class then you have to declare the body of the method in parent class which you have in child class. then it will be visible and this concept is called method overriding.
If you don't need to create the object of your super class then you can declare class as abstract and then you can simply put that method as abstract keyword shown as below.
abstract class Alpha
{
String getType1()
{
return "alpha";
}
abstract String acc();
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
#Overriding
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Child classes are privileged to access to default constructor of parent class until unless you have restricted it with private access modifier.
Your cases is an example of method overloading. Actual call to overloaded method is resolved at run time. Which method will be called, depends on the concrete object not type of object. Here your reference is of type Alpha but the object is of Type Beta. So method getType1() here will print beta which is correct behavior.
In the book Java: The complete reference
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor
It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.
Why did the Java Language designers consider it necessary to do so?
As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.
As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.
Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.
To illustrate this, consider a very simple set of classes:
public class Super {
private final String name;
Super() {
name = "default";
}
public String name() {
return name.toUpperCase();
}
}
public class Sub extends Super {
public Sub() {
// don't do anything
}
}
When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.
You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.
Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
more here
Because it says so in the Java Language Specification.
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:
public abstract class TestA {
private int a;
public TestA()
{
a=10;
}
public int displayA()
{
return a;
}
abstract void display();
}
public class TestB extends TestA{
#Override
void display() {
System.out.println("this is class B");
}
}
package Abstract;
public class TestMain {
public static void main(String[] args) {
TestA obj= new TestB();
System.out.println(obj.displayA());
}
}
Output is : 10
Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.
Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties
class A {
protected int a;
A() {
a=12;
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
System.out.println(a);
}
}
public class ConstructorInheritance {
public static void main(String args[]) {
B b=new B();
}
}
output:
Inside A's constructor.
Inside B's constructor.
12
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".
Thus, constructor of super class have to be called. There is sequence how the constructor processed:
Call super class constructor
Initialize fields with initializers and initialization blocks
Execute body of the constructor
For more details, have a look of the book to section "3.2".
public class B extends A{
public static void main(String[] args) {
new B().privateMethod();//no error -output B-privateMethod.Sounds like overriding
new B().staticMethod(); //no error -output B-StaticMethod.Sounds like overriding
}
private void privateMethod() {
System.out.println("B-privateMethod.");
}
static void staticMethod() {
System.out.println("B-StaticMethod.");
}
}
class A{
private void privateMethod() {
System.out.println("A-privateMethod.");
}
static void staticMethod() {
System.out.println("A-StaticMethod.");
}
}
On R&D I found in case of privateMethod()- since this method was not available on object of child class so child class's and parent class's privateMethod() are separate method and they have no relationship so this is not overriding.
but in case of staticMethod()- parent class's method was available on object of child class ,and when we define this in child class, object of child class start pointing to child class method.this looks like method overriding but not,since static method does not override.
how does static method handle by java developement kit?
new B().privateMethod();
this is not overriding, since B doesn't see A's privateMethod().
new B().staticMethod();
this is not overriding, calling a static method via an instance is allowed, though it can be confusing. It is exactly the same as calling it via the class name - B.staticMethod(). If a super class A of B has a static method visible from B, you can call that method from B (and it doesn't matter if you write B.staticMethod() or A.staticMethod() or new B().staticMethod().
If later you define a static method of the same name in B, that method hides the method of the same name in A, so calling B.staticMethod() or new B().staticMethod() now invokes B's static method. However, calling A.staticMethod() will still invoke A's static method.
Polymorphism is not for static methods. Static methods are called with JVM instructions invokestatic, whereas polymorphism is achieved with invokevirtual. The calls to static methods are determined at compile time, and polymorphic methods are dynamically dispatched at runtime.
You can easily tweak your code so that A.staticMethod() is called, by just assigning new B() to a variable of type A.
public static void main(String[] args) {
new B().privateMethod();
A b = new B(); // change here.
b.staticMethod(); // A.staticMethod() is called here.
}
Never speak about static and override in the same sentence.
The whole concept of overridable methods is to dynamically bind at runtime which method is to be executed. Consider this:
class A { void print() { out.println("A"); }
class B extends A { void print() { out.println("B"); }
A obj = new B();
obj.print();
Although the variable obj is of type A, it still prints out "B".
Static methods on the other hand are bound at compile time. This means the compiler uses the type of the variable (or the expression) to determine what method to execute:
class A { static void print() { out.println("A"); }
class B extends A { static void print() { out.println("B"); }
A obj = new B();
obj.print();
This now yields "A". Unfortunately the Java language allows to call static methods on variables or expressions. This is not recommended! Better call static methods on the type itself:
A.print();
B.print();
In the first example - obj.print(); - the compiler automatically translates the statement into A.print(). The actual object does not count. In fact you could write the following:
A obj = null;
obj.print();
Or:
((A) null).print();
That still prints "A".