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
Related
My code looks like this:
public abstract class BaseClass{
public void update() {
//...
}
public void somethingHappenedSoCallUpdate() {
update();
}
}
public class ExtendingClass extends BaseClass{
#Override
public void update() {
//...
}
}
There's an instance of ExtendingClass and at some point method somethingHappenedSoCallUpdate() is called. And I expect the method will call BaseClass.update() but ExtendingClass.update() is called. Can someone explain why?
And I expect the method will call BaseClass.update() but ExtendingClass.update() is called. Can someone explain why?
Because that's how Java is defined. By default, all non-private methods are virtual, which means that when you have overridden methods, the method that gets called on an instance is the instance's most-overridden version (ExtendingClass's, in your case), regardless of the type reference through which the method call is made. This is fundamental to polymorphism in modern OOP languages.
The compile-time type reference tells the compiler whether code has access to the method; the runtime type of the object tells the JVM which override of the method to call.
Let's take a simple example:
class Base {
public void method1() {
System.out.println("Base#method1");
}
}
class Derived extends Base {
#Override
public void method1() {
System.out.println("Derived#method1");
}
public void method2() {
System.out.println("Derived#method1");
}
}
// Usage:
Base b = new Derived();
b.method1(); // Calls Derived#method1, the most-overridden version the
// actual object has
b.method2(); // Fails to compile; Base doesn't define method2, so the
// code doesn't have access to call it when using a Base
// reference, even though the object does have the method
As #hyde said, Java methods are virtual, thats means that the VM decides at runtime which method to invoke. If you call somethingHappenedSoCallUpdate() on an instance that extends BaseClass then BaseClass.somethingHappenedSoCallUpdate() will be called, but since ExtendingClass is overriding BaseClass.update() it will class ExtendingClass.update() instead of BaseClass.update().
When extending a method you have to think of it like this:
whenever you extend a method you put it on a stack and when you invoke it, Java will look on this "stack" and invokes the topmost. That means if you have a BaseClass that has a update() method, this class can be extended by X classes not overriding the update() method but if the X+1 class does, Java will always call that method of X+1.
It's polymorphism:the right method is called at runtime depending on the real type of the object it's a dynamic binding.
Because you overrode update in subclass and since java methods are virtual overridden version is called.
Option #1
Override update, override somethingHappenedSoCallUpdate() method and use there super.update() instead of update().
Option #2
Make update private in superclass:
private void update()
You overrode the method so if you still want the code in the abstract class to run you need to implicitly call update() within the overridden method. So...
public class ExtendingClass extends BaseClass {
#Override
public void update() {
super.update(); // Call the base method.
}
}
Hope that helps :)
In the below program I am overriding a static and a instance method, When I call the instance method using the superclass it is executing the subclass method, but in case of the static method it is executing superclass static method. Why is this?
class Superclass
{
public void print()
{
System.out.println("superclass print");
}
public static void staticPrint()
{
System.out.println("Superclass static print");
}
}
public class Subclass extends Superclass
{
public static void staticPrint()
{
System.out.print("subclass staticPrint");
}
public void print()
{
System.out.println("subclass print");
}
public static void main(String... args)
{
Subclass subclass=new Subclass();
Superclass superclass=subclass;
superclass.staticPrint();
superclass.print();
}
}
Output:
Superclass static print
subclass print
Static methods cannot be overridden, the can only be hidden, as for variables.
Take a look here for further details:
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
There is no method overriding for static methods. superclass.staticPrint() is equivalent to Superclass.staticPrint().
The type of the instance referred by the superclass variable doesn't matter at all when calling a static method. It can even contain null and the static method staticPrint() of Superclass class will still be executed.
first of all a static method cannot be overridden.
when referring to a static method or variable, it will always use the default of the class declared
Subclass subclass=new Subclass();
Superclass superclass=subclass;
superclass.staticPrint();
a static method does not need to be instantiated. the only important thing is that superclass was declared as type Superclass.
while an instance method will always refer to its "Instance" implementation as the implementation is dependent on state of an object.
Subclass subclass=new Subclass();
Superclass superclass=subclass;
superclass.staticPrint();
superclass.print();
since superclass was instantiated as a Subclass. it will call the subclass implementation since an instance method requires a state to execute.
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)
I'm having trouble wrapping my head around the concept of super(). Java Tutorials gives this example:
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
But if I am overriding the printMethod, why do I need to invoke the Superclass method? Why can't I just write whatever in the Subclass method of printMethod() and just move on?
There is absolutely no need to call the super.
It just helps you to call the logic contained within super class method if you require that.
Many times you want the exact logic to run and then provide your additional logic.
Overriding always does not mean providing brand new logic. Sometimes you want to provide a slight variation. For e.g., if the method returns a value, then you call the super class method and get the value. Then you make some slight modification in that object using logic in the sub class method and return it back to caller.
You can override it. In that case, the parent method is ignored. super() is used if you want the parent method to be executed in the subclass.
This is used to avoid duplicated code. Let's say you have a class:
public class SuperClass() {
private int var1;
private int var2;
private int var3;
public SuperClass() {
var1 = 1;
var2 = 2;
var3 = 3;
}
}
and a subclass:
public class SubClass() {
private int var1;
private int var2;
private int var3;
private int var4;
public SubClass() {
super();
var4 = 4;
}
}
In this example, you are using super() to invoke superclass constructor (constructor are usually used to initialize members) so you can focus on the SubClass members, and you don't have to repeat all the initialization lines (for var1, var2 and var3).
Basically the super class is the upper most level of the program. When you create a new subclass you must "inherit" from the super class using the keyword 'extends'. This does 2 things; It allows you to use any methods created in the super class, in the subclass and it also allows you overwrite methods in the super class. Basically, if you have one method you want to use in a bunch of classes you use the super class to create it and then the sub-classes can just call the method using standard dot notation.
If you just run this program, Inside PrintMethod of the subclass will call to super class "printMethod" (print "Printed in Superclass") and then execute the things you have written in the sub class method(print "Printed in Subclass").
public void printMethod() {
//super.printMethod(); // comment this line
System.out.println("Printed in Subclass");
}
if you run like this, it will print only the things that you have written in the sub class method.
Idea is, If you want use Super class method information in the sub class, then you can call like Super.MethodName().
Clear Explanation :
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
Subclass s = new Subclass();
(i) when we are creating sub class object what wiill happens?
constructor of subclss will be executed
(ii) Do we have any costructor in sub class (Subclass )
if we have dat will execute..
but we are not having so default costructor will excecute
(iii) what default costructor will have?
Subclass (){
super();
}
(iv) what super() will do?
it calls super class contructor
in super class also we are not having constructor so
will execute default constructor
Superclass(){
super();
}
super class of superclass is Object class
so Object class is the super class of evry class in java
so it will creates object of object class..
object of Object class created
|
and comes to its subclass constructor...//step (iv)
Superclass(){
super(); // executed
}
object of Object class created
|
object of Superclass craeted
so super class constuctror execution also completed so
it will creates Object of SuperClass..
then control comes to its subclass conctructor // step (iii)
so Subclass (){
super(); // executed
}
after completion of subclass constructor it creates the object of subclass
*Important point : after completion of constructor execution
Object of thet class will be created*
object of Object class created
|
object of Superclass craeted
|
object of Subclass craeted
all this happened because of Subclass s = new Subclass();
so when you created object of sub class 3 objects are created..
s.printMethod();
now you are calling a method on subclass object
^
printMethod() is there in super class and sub class
when u r calling a method on sub class object what happens?
(i) it will search for that method in outer most objest: Object of Object class
so now printMethod() is not there in object of object class
(ii) Next its searches in next superclass object ie. object of Superclass
object Superclass object having printMethod() method
(iii) so method found...eventhougth method found controll serches in next sub most object is object of subclass object....
(iv) two methos found in two object but it excecutes sub most object method.
so sub most object is Subclass object...
so it executes the subclass printMethod() method.
Note: when we call a method on object it will executes the sub most objects method if ovverriden.....
now our method is....
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
first line in this method is super.printMethod();
by default super ponts to super class object : object of Superclass
object of Superclass .printMethod() is
public void printMethod() {
System.out.println("Printed in Superclass.");
}
so prints :
Printed in Superclass.
next line is : System.out.println("Printed in Subclass");
so it prints : Printed in Subclass
Note : first while creating object it called super class constructor..
now in method called super class method..
Note:
1.if class not having any constructor jvm assigns default constructor as
ClassName(){
super(); calls super class constructor
}
if class alrdy having constructor
the first line of the constructor should be the super() call.
for example: class A{
int variablea;
A(int a){
variablea=a;
}
public static void main(String[] args) {
A a=new A(2);
}
}
in this example
A(int a){
variablea=a;
} code replaces with
A(int a){
super(); by jvm by default
variablea=a;
}
You can use super in a subclass to refer to its immediate superclass. Super has two general forms.
to call the super class's constructor from the subclass
to access a member of the superclass from the subclass
I'm assuming that you are trying to understand the second one.
An example which might make you understand how super helps in referencing members of the super class:
public class Human {
String name;
int age;
public void printDetails() {
System.out.println("Name:"+name);
System.out.println("Age:"+age);
}
}
public class Student extends Human {
int rollNumber;
String grade;
public void printDetails() {
super.printDetails();
System.out.println("Roll Number:"+rollNumber);
System.out.println("Grade:"+grade);
}
public void printNameAgeAndSayGoodMorning(){
super.printDetails();
System.out.println("Good morning!");
}
public static void main(String[] args) {
Student s = new Student();
s.name="MyName";
s.age=27;
s.rollNumber=3;
s.grade="A+";
s.printDetails();
System.out.println(); //just an empty line
s.printNameAgeAndSayGoodMorning();
}
}
I avoided constructors or any getter/setter methods for simplicity.
In this example, do you think you really have to "just write whatever in the Subclass" instead of reusing the printDetails() method available in the super class?
class A {
A() {
System.out.print("A");
}
}
class B extends A {
B() {
System.out.print("B");
}
}
class C extends B {
C() {
System.out.print("C");
}
}
public class My extends C {
My(){
super();
}
public static void main(String[] args) {
My m = new My();
}
}
Question starts from one Interview Question (what happens when an object is created in Java?)
and answer is...
The constructor for the most derived class is invoked. The first
thing a constructor does is call the consctructor for its
superclasses. This process continues until the constrcutor for
java.lang.Object is called, as java.lang.Object is the base class for
all objects in java. Before the body of the constructor is executed,
all instance variable initializers and initialization blocks are
executed. Then the body of the constructor is executed. Thus, the
constructor for the base class completes first and constructor for the
most derived class completes last.
So, according to above statement, answer should be ABCC, but it showing only ABC. Although, when i'm commenting the super() in derived constructor. Then, output is ABC. Please, help me to figure out, did i misunderstand the above paragraph. ?
No, the answer is ABC
My m = new My();
The above first invokes My class, then a super call is made to its super class i.e., C class, then a super call to B class is made, then a super call to A Class, then a Super call to java.lang.Object as all objects extend java.lang.Object.
Thus the answer is ABC.
You don't really need to explicitly call super() in your My class as it'd be included by the compiler unless you call an overloaded constructor of that class like this(something).
The below code will print ABC
To invoke the constructor of the super class, the compiler will implicitly call the super() in each and every class extending the class, if you are not calling the super construcotr explicitly.