the issues of calling overridable methods from constructor - java

if it is possible please make this sentence clear for me
here, the author said:
Do not call overridable methods from constructors. When creating a
subclass object, this could lead to an overridden method being called
before the subclass object is fully initialized. Recall that when you
construct a subclass object, its constructor first calls one of the
direct superclass’s constructors. If the superclass constructor
calls an overridable method, the subclass’s version of that method
will be called by the superclass constructor—before the subclass
constructor’s body has a chance to execute.
i can't understand that how it can be possible to call a subclass's version of the overridable method in the superclass's constructor
TnX

You have to first make a distinction between instantiation and initialization. Instantiation is the process of creating an instance of a type (allocating the space for it and getting a reference to that space). Initialization is the process of setting the state of the instance to its initial value.
Take the following type hierarchy:
class Foo {
public Foo() {}
}
class Bar extends Foo {
public Bar() {super();}
}
New instance creation expressions
new Bar();
cause instantiation and initialization. Instantiation happens first. Java creates an instance of concrete type Bar.
Then initialization needs to take place. In an inheritance hierarchy, the initialization follows the same hierarchy, but top to bottom.
Object
|
Foo
|
Bar
The constructor for Object runs first to initialize the state that is defined as part of Object, then the constructor for Foo is run to initialize the state that is defined as part of Foo and finally the constructor for Bar is run to initialize the state defined in Bar. Your instance is still of type Bar. So polymorphism still applies. If you invoke an instance method and that method is overriden somewhere lower in the hierarchy, that implementation will be invoked.
That's what that quote is referring to. It's dangerous. Read more here:
What's wrong with overridable method calls in constructors?

To illustrate the reason this is a bad idea with some (simplistic) code, consider these two classes:
class Greeter {
protected Greeter() {
printHello();
}
protected void printHello() {
System.out.println("Hello");
}
}
Looks simple enough, it prints Hello whenever you instantiate it. Now lets extend it:
class NamedGreeter extends Greeter {
private String name;
public NamedGreeter(String name) {
this.name = name;
}
#Override
protected void printHello() {
System.out.println("Hello " + name);
}
}
The intent is clearly to have the NamedGreeter greet you by name when instantiated, but in fact it will always print Hello null because the super constructor is called first when the NamedGreeter is instantiated.
Thanks to how polymorphism works, any time the printHello() method is called on a NamedGreeter (even if that call is from within the Greeter class) the implementation in NamedGreeter will be called. Calling that method from within the constructor of the parent class means that even if the child class extends it then no fields defined by the child will be initialized, simply because it's not possible to do anything in the child constructor (like initialize fields) before the parent constructor is called.

An example demonstrating that the child method will be invoked:
class Foo {
static class Parent {
Parent() {
someMethod();
}
void someMethod() {}
}
static class Child extends Parent {
#Override void someMethod() {
throw new AssertionError("Invoked");
}
}
public static void main(String[] args) {
new Child(); // Throws Exception.
}
}
Output:
Exception in thread "main" java.lang.AssertionError: Invoked
at Foo$Child.someMethod(Foo.java:16)
at Foo$Parent.<init>(Foo.java:9)
at Foo$Child.<init>(Foo.java:14)
at Foo.main(Foo.java:21)

Related

Polymorphism: calling subclass' method from superclass' variable

In Java, when a method is going to be executed, it's declaration is first searched for at the object's real class (that defines the real type of the object). If it's not found, then the superclass is checked. If isn't found there either, the next parent class is checked, and so on. However, look at the example below:
SuperClass s = new SubClass(list of parameter);
s.someMethodExistOnlyInSubClass();
This will give me a compile time error. I thought that, as mentioned above, it would first look for someMethodExistOnlyInSubClass() at SubClass, verify that it exists there and then execute it right away. If I use a variable of the type SuperClass to reference an instance of SubClass some parameters will go to SuperClass's constructor through a call to super() and the object will be instantiated there. In this context, to where have the remaining parameters gone?
By assigning a reference to an instance of SubClass to a variable of the type SuperClass, the variable is treated as if it were referencing an instance of SuperClass. Therefore, it will have no knowledge of any of the methods declared specifically in SubClass. Note, though, that the overrides performed in SubClass will still be effective.
In the context you described, to access someMethodExistOnlyInSubClass() you would have to cast s to the type SubClass. Look below:
((SubClass) s).someMethodExistOnlyInSubClass();
What you are trying to do will work only when the method is defined in both Parent class and subclass.
import java.util.*;
class Parent
{
public void sample()
{
System.out.println("Method of parent is getting Called");
}
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Parent p = new Subclass();
p.sample();
}
}
OUTPUT : Method of Child class is getting Called
If the method exists only in Child class. You will have to create an instance of Child class itself.
Something like this :
import java.util.*;
class Parent
{
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Subclass p = new Subclass();
p.sample();
}
}
Or you can type cast it as mentioned in the earlier post
Parent p = new Subclass();
((Subclass)p).sample();
An object is created based on its declaring class.
When you declare it as SuperClass s the object s wont have any method called someMethodExistOnlyInSubClass . So when you try to invoke this method, even before look at the subclass, you get a compile error.
The object s contrains only everything of the superclass, this object wont be aware of any subclass until u type cast the object to subclass.

Logic behind polymorphism in this example:

class Base {
public static void staticMethod(Base bObj) {
System.out.println("In Base.staticMethod()");
bObj.instanceMethod();
}
public void instanceMethod() {
System.out.println("In Base.instanceMethod()");
}
}
class Derived extends Base {
public static void staticMethod(Base bObj) {
System.out.println("In Derived.staticMethod()");
bObj.instanceMethod();
}
public void instanceMethod() {
System.out.println("In Derived.instanceMethod()");
}
}
public class Main {
public static void main(String []args) {
Base bObj = new Derived();
bObj.staticMethod(bObj);
}
}
Initially, when I saw this example I was sure that the result would be:
"In Base.staticMethod()"
"In Base.instanceMethod()".
After the initialization of the first Derived object it is obvious that it will be interpreted as a Base object due to upcast and it will call the static method of the base class which it does but later when it calls the other method(instance method) it goes inside the derived function instead of base class.
Why, considering that initially it was considered being Base?
There is no method overriding for static methods. Therefore bObj.staticMethod(), which is equivalent to Base.staticMethod, invokes the static method of the base class.
Inside the static method you are calling bObj.instanceMethod(). For instance methods there is method overriding, and the runtime type of bObj determines which method is executed - the instance method of Derived in your case.
Override is only for instance methods. For Static Method the term is called Method Hiding See Detail.
1. If method hiding is used then BaseClass's method is hidden from Subclass. method selection solely depends on which class's reference you are using to call the method. In your example since you are using BaseClass (even you assign Subclass object, it still on the class level it's BaseClass) reference to make a call to the static method it makes a call to BaseClass's method. If you would use SubClass reference as below then it would call the SubClass's static method
public static void main(String []) {
Derived bObj = new Derived();
bObj.staticMethod(bObj);
}
As the call inside the static method is for an Instance method. It uses polymorphism here and calls the SubClass's method.
TL;DR:
bObj.staticMethod(bObj); only looks at the compile-time type of bObj, and is equivalent to Base.staticMethod(bObj); in your case. There's no overriding.
bObj.instanceMethod(); only looks at the runtime class of bObj, and selects the method based on that class. So overriding works here.
Explanation
If you call a static method, you should do so by naming the class, not an instance. So bObj.staticMethod(bObj) should better be written Base.staticMethod(bObj). Typically, the compiler will issue a warning for the first version.
That's because the runtime instance is irrevant for selecting the static method. The decision is made by the compiler. And that's why we call this method type "static", because it lacks the dynamic method lookup of instance methods. That means that there is no overriding based on the instance "before the dot".
Using an instance expression misleads the reader into thinking the instance were relevant, and therefore should not be used. And inside the static method, there is no way to refer to the instance "before the dot". The keyword this doesn't exist in static methods. To call a static method, you don't even need an instance of that class (e.g. you can't create Math instances, but you can call Math.min() without any problem).
On the other hand, if you call an instance method, you need an instance of a class having that method, and this instance gets the name this inside the method. The method selection is done at runtime, based on the runtime class of the instance, no matter what the declared type is.

Does object in java created on heap before Constructor is invoked?

When overridden methods are called from the Constructor of the base class then also as per the run time polymorphism concept the method defined in the sub class gets invoked. I wonder as how this is taken care of in the JVM, when control is in the base class constructor the constructor of the sub class is yet to be called and hence Object is not yet completely constructed.
I understand the ill effects of calling overriden methods from base class constructor but just wish to understand as how this is made possible.
I feel object in the heap is created before constructor is invoked and as constructor is invoked the properties are initialized. Please provide your valuable inputs for the above.
Below is the code demonstrating the same.
Base.java
public class Base {
public Base() {
System.out.println("Base constructor is executing...");
someMethod();
}
public void someMethod() {
System.out.println("someMethod defined in Base class executing...");
}
}
Sub.java
public class Sub extends Base{
public Sub() {
System.out.println("Sub constructor is executing...");
}
#Override
public void someMethod() {
System.out.println("someMethod defined in Sub class executing...");
}
}
Client.java
public class Client {
public static void main(String[] args) {
Sub obj = new Sub();
}
}
Output on console is
Base constructor is executing...
someMethod defined in Sub class executing...
Sub constructor is executing...
Does object in java created before Constructor is invoked ?
Yes, otherwise you would not have an object to initialise.
At the byte code level, the object is created first, and then the constructor is called, passing in the object to initialise. The internal name for a constructor is <init> and it's return type is always void meaning it doesn't return the object, only initialise it.
Note: Unsafe.allocateInstance will create an object without calling a constructor and is useful for de-serialization.

Java NullPointerException when extending parent class

I'm getting NullPointerException whith below code.
Parent.java
public abstract class Parent {
public Parent(){
parentFunc();
}
public abstract void parentFunc();
}
Child.java
public class Child extends Parent {
ArrayList<String> list = new ArrayList<String>();
#Override
public void parentFunc() {
list.add("First Item");
}
}
when I create and instance of Child like new Child() I'm getting NullPointerException
Here is my console output
Exception in thread "main" java.lang.NullPointerException
at Child.parentFunc(Child.java:8)
at Parent.<init>(Parent.java:5)
at Child.<init>(Child.java:3)
at Main.main(Main.java:8)
I know that exception occurs because of Child.parentFunc() which called in parent constructor, but I really got confused. So I wonder what is going on
What is the order of creation;
When list variable is created
When constructors are called
When functions are created and called which called in constructors
When list variable is created?
It will be created once constructor of Child class runs.
When constructors are called?
When you try to make an object using new Child(), constructor is called for Child and it internally calls super() which calls the superclass constructor Parent().Note that the very first statement in Child() constructor is super().
The system will generate no-arguement constructor for you like this:
public child()
{
super();// calls Parent() constructor.
//your constructor code after Parent constructor runs
}
When functions are created and called which called in constructors
Clear out a bit what are you trying to ask .
Order Of Execution:
Parent Constructor->Child Constructor-->List
When parent constructor invoked the function called , You list not initialized and defailu value to the Object null is there,
#Override
public void parentFunc() {
list.add("First Item"); // list not yet initialized
}
You have an implicit Child() constructor. It calls Parent(), Parent() calls parentFunc() which is called in the sub-class. At that moment your list is still null and you get the NullPointerException (NPE).
See also:
Java Constructor and Field Initialization Order
It's usually a bad idea to call abstract methods from a constructor, as you exposed yourself to this kind of problem.

java override method invocation

I have a super class:
public class SuperClass {
public void dosomething() {
firstMethod();
secondMethod();
}
public void firstMethod() {
System.out.println("Super first method");
}
public void secondMethod() {
System.out.println("Super second method");
}
}
A sub class:
public class SubClass extends SuperClass {
public void dosomething() {
super.dosomething();
}
public void firstMethod() {
System.out.println("Sub first method");
}
public void secondMethod() {
System.out.println("Sub second method");
}
}
A test class:
public static void main(String[] args) {
SubClass sub = new SubClass();
sub.dosomething();
SuperClass sup = new SuperClass();
sup.dosomething()
}
when I run the test method, I got this:
Sub first method
Sub second method
Can you tell me how this happened? In the sub class dosomething method, I called super.dosomething() and I think the super method will be called, but the override method in sub class was called.
if I do this:
SuperClass superClass = new SuperClass();
superClass.dosomething();
the result is:
Super first method
Super second method
The difference is method invocation place. I think there must be something I don`t know ):
oops!the super reference pointed to subclass in the first example...
like this:
SuperClass sub = new SubClass();
sub.firstMethod();
sub.secondMethod();
In java, the methods binding is always dynamic [ignoring static and private methods here]. Thus, when you override firstMethod() and secondMethod(), any time an object of type SubClass will try to invoke one of them - the overriden method will be invoked - even if it [the invokation] is from the parent's method.
So, as expected - when you invoke super.doSomething(), it calls firstMethod() and secondMethod(), and the overriden methods are being called.
Your object on which the methods are invoked is of type SubClass, not SuperClass. Even if you call a method that is only defined in SuperClass, your execution context remains SubClass. So any method that is invoked that is overridden will in fact execute the overridden method.
The thing to take away from this is that by declaring firstMethod and secondMethod as public, SuperClass is in fact allowing subclasses to override their behaviour. If this is not appropriate, the methods should be private, or final.
Indeed the super doSomething gets called. Do something calls firstMethod and secondMethod, which are virtual methods (any method in Java is by default virtual, which means it can be overriden). So their overriden versions gets called.
You can prevent them from being overriden if you mark them final.
Super.dosomething() does in fact call the method dosomething() in Super class. But inside this method, you call 2 functions which are firstMethod and secondMethod. These methods are overwritten in the Sub class and they are being called from the Sub Class.
As Petar Ivanov suggested:
You can prevent them from being overriden if you mark them final

Categories

Resources