Difference between "this" and"super" keywords in Java - java

What is the difference between the keywords this and super?
Both are used to access constructors of class right? Can any of you explain?

Lets consider this situation
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void anotherEat() {
super.eat();
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eat();
d.anotherEat();
}
}
The output is going to be
animal : eat
dog : eat
animal : eat
The third line is printing "animal:eat" because we are calling super.eat(). If we called this.eat(), it would have printed as "dog:eat".

super is used to access methods of the base class while this is used to access methods of the current class.
Extending the notion, if you write super(), it refers to constructor of the base class, and if you write this(), it refers to the constructor of the very class where you are writing this code.

this is a reference to the object typed as the current class, and super is a reference to the object typed as its parent class.
In the constructor, this() calls a constructor defined in the current class. super() calls a constructor defined in the parent class. The constructor may be defined in any parent class, but it will refer to the one overridden closest to the current class. Calls to other constructors in this way may only be done as the first line in a constructor.
Calling methods works the same way. Calling this.method() calls a method defined in the current class where super.method() will call the same method as defined in the parent class.

From your question, I take it that you are really asking about the use of this and super in constructor chaining; e.g.
public class A extends B {
public A(...) {
this(...);
...
}
}
versus
public class A extends B {
public A(...) {
super(...);
...
}
}
The difference is simple:
The this form chains to a constructor in the current class; i.e. in the A class.
The super form chains to a constructor in the immediate superclass; i.e. in the B class.

this refers to a reference of the current class.
super refers to the parent of the current class (which called the super keyword).
By doing this, it allows you to access methods/attributes of the current class (including its own private methods/attributes).
super allows you to access public/protected method/attributes of parent(base) class. You cannot see the parent's private method/attributes.

super() & this()
super() - to call parent class constructor.
this() - to call same class constructor.
NOTE:
We can use super() and this() only in constructor not anywhere else, any
attempt to do so will lead to compile-time error.
We have to keep either super() or this() as the first line of the
constructor but NOT both simultaneously.
super & this keyword
super - to call parent class members(variables and methods).
this - to call same class members(variables and methods).
NOTE: We can use both of them anywhere in a class except static areas(static block or method), any
attempt to do so will lead to compile-time error.

this is used to access the methods and fields of the current object. For this reason, it has no meaning in static methods, for example.
super allows access to non-private methods and fields in the super-class, and to access constructors from within the class' constructors only.

When writing code you generally don't want to repeat yourself. If you have an class that can be constructed with various numbers of parameters a common solution to avoid repeating yourself is to simply call another constructor with defaults in the missing arguments. There is only one annoying restriction to this - it must be the first line of the declared constructor. Example:
MyClass()
{
this(default1, default2);
}
MyClass(arg1, arg2)
{
validate arguments, etc...
note that your validation logic is only written once now
}
As for the super() constructor, again unlike super.method() access it must be the first line of your constructor. After that it is very much like the this() constructors, DRY (Don't Repeat Yourself), if the class you extend has a constructor that does some of what you want then use it and then continue with constructing your object, example:
YourClass extends MyClass
{
YourClass(arg1, arg2, arg3)
{
super(arg1, arg2) // calls MyClass(arg1, arg2)
validate and process arg3...
}
}
Additional information:
Even though you don't see it, the default no argument constructor always calls super() first. Example:
MyClass()
{
}
is equivalent to
MyClass()
{
super();
}
I see that many have mentioned using the this and super keywords on methods and variables - all good. Just remember that constructors have unique restrictions on their usage, most notable is that they must be the very first instruction of the declared constructor and you can only use one.

this keyword use to call constructor in the same class (other overloaded constructor)
syntax: this (args list); //compatible with args list in other constructor in the same class
super keyword use to call constructor in the super class.
syntax: super (args list); //compatible with args list in the constructor of the super class.
Ex:
public class Rect {
int x1, y1, x2, y2;
public Rect(int x1, int y1, int x2, int y2) // 1st constructor
{ ....//code to build a rectangle }
}
public Rect () { // 2nd constructor
this (0,0,width,height) // call 1st constructor (because it has **4 int args**), this is another way to build a rectangle
}
public class DrawableRect extends Rect {
public DrawableRect (int a1, int b1, int a2, int b2) {
super (a1,b1,a2,b2) // call super class constructor (Rect class)
}
}

Related

What does "extends" actually do?

I am currently studying the concept of "class abstraction" and "extension" and have been wondering:
"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"
I understand the fact that extension instances the previous abstract class into the extended one and tries to call the default constructor but have been wondering why it gives out an error.
Is it because the constructor has been parametrized or simply because the empty constructor does not exist?
Does the extends keyword call something along the lines of this?
Object myClass = new AbstractClass();
And the missing parameters are the reason why it gives out an error so something along the lines of this would be correct
Object myClass = new AbstractClass(int foo,float boo);
And if that is it, does the super keyword essentially, if you'll allow me the term, "put" the parameters given in the parenthesis "inside" the constructor?
If that's not it what am I getting wrong? How does it actually work?
You should think of the extends keyword, in this context, as just saying that a class is the subclass of another class, and does nothing else. And that there are rules governing how subclasses and superclasses should work.
When you construct a subclass, you must construct its superclass first. For example, to create a Bird, you must first create an Animal. That makes sense doesn't it? To demonstrate this in code:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
Doing new Bird() will first print Animal and then Bird, because the Animal's constructor is called first, and then the Bird constructor. So actually, the Bird constructor implicitly calls the superclass' constructor. This can be written as:
public Bird() {
super();
System.out.println("Bird");
}
Now what happens if the super class does not have a parameterless constructor? Let's say the constructor of Animal now takes a String name as argument. You still need to call the superclass' constructor first, but super() won't work because super() needs a string parameter!
Therefore, the compiler gives you an error. This can be fixed by calling super() explicit with a parameter.
"If I declare a parametrized constructor inside my abstract class why
won't extension on another class work unless I declare myself the
constructor with the super keyword invoking the parameters of the
abstract class's constructor?"
Because the super class says that it MUST be constructor using that declared constructor and there is no other way around. This applies to every extending class - required constructor must be called.
The same happens with any class when you declare other constructor than default one. For example, having
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
so then
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
The same applies when you are extending classes. To construct child instance, you must first "internally create parent instance" calling super.constructor. Since there is no default constructor, ANY of explicit declared superconstructors must be used.
When initializing an Object the constructor will always be called. Even if you do not define one constructor there will be a default one without any parameters. So if you define a constructor in the abstract class, you have to call that constructor with super().
If you do not define any constructors, then it will be implicitly called as the default one.
If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?
There is no default constructor available in AbstractClass since you define a parametrised constructor. If you don't define a constructor yourself, a default constructor without arguments is implicitly created. You can manually add such one now or you need to use the only available constructor (which is parametrised) with super().
Example of your code with defining constructor without arguments:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
Example of your code with calling super() with arguments:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();

Just like superclass members, do superclass constructors form part of the subclass object state?

Please allow me to explain my understanding.
class P
{
P()
{
System.out.println("hi "+this);
/*which object of P is currently executing this constructor?
Is "this" here object referenced by q or some other object?*/
}
}
class Q extends P
{
Q()
{
super();
/*constructor of superclass called on this object(referenced by q) */
}
}
class R
{
public static void main(String args[])
{
Q q = new Q(); //constructor Q() invoked on object referenced by q
}
}
So my doubts are:
1. super() is invoked on which object of P(since none exists).
2. What is "this" in P() referring to? Is it the same object as q? In other words is this=q ?
Code, ctors included, does not define 'object state'. Set of instance fields do. And, under the hood, subclass instances do include private fields of their superclasses, but javac makes sure that they only accessible, directly or indirectly, by calling superclass methods (ctors included).
Regarding your updated question:
class Q extends P
{
Q()
{
super(); /*constructor of superclass called on this object(referenced by q) */
}
}
Here Q extends P, so super() calls P's ctor. During execution of P's ctor, this allows to refer to fields and methods belonging to P and to it's supertypes (e.g., Object) w/ restrictions imposed by access modifiers (I mean you can access only public and, w/ restrictions protected and 'package-private' members of subtypes), but not to P's subtypes.
Regarding "no access to P's subtypes" rule there's one more twist: if you call some non-private (overridable) method of P from P's ctor, chances are this method will be overridden someday in Q or other subtype, and you suddenly start calling some unforeseen code! So, this inside P does allow to refer explicitly to P's subtype methods but not to P's subtype fields (although implicitly P's fields can be reached by P's subtype method).
To give an example -- change f() in following code from private to 'package-local' and witness a NPE thanks to following execution chain Derived#Derived() -> Base#Base() -> Derived#f() -> NPE!:
class Base {
private Integer base = 1;
Base() {
f();
}
private void f() {
System.out.println(base);
}
}
class Derived extends Base {
private Integer derived;
Derived() {
super();
derived = 2;
f();
}
private void f() {
System.out.println(derived.intValue());
}
}
Constructors are not inherited to subclasses. And using super() you can just call the super class constructor. You can not access the private variable/property of super class from subclass. Moreover private member of a super class is also not inherited to it's subclass.
Constructors are not inherited in java.
As per the official Java tutorial:
A subclass inherits all the members (fields, methods, and nested
classes) from its superclass. Constructors are not members, so they
are not inherited by subclasses, but the constructor of the superclass
can be invoked from the subclass.
When you call super() you simply invoke the parent constructor, which can access private members of the class it belongs to.
As for the updated version of your question:
As mentioned above, super() simply invokes the parent constructor. It's not invoked on any object, since constructor is not a member of a class.
this in the P constructor will refer to the instance of a subclass (Q) that is being constructed.
EDIT:
Regarding 2. This can be easily verified by outputting the reference q in your main method. It should print exactly the same that the System.out.println(this) call in the P constructor.
public class R
{
public static void main(String args[])
{
Q q = new Q(); //constructor Q() invoked on object referenced by q
System.out.println(q);
}
}

Java compiler super() constructor generals [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of ‘super’ keyword when accessing non-overridden superclass methods
I'm new to Java and have been reading a lot about it lately to get more knowledge and experience about the language. I have a question about inherited methods and extending classes when the compiler inserts automatic code.
I've been reading that if I create class A with some methods including lets say a method called checkDuePeriod(), and then create a class B which extends class A and its methods.
If I then call the method checkDuePeriod() within class B without using the super.checkDuePeriod() syntax, during compilation will the compiler include the super. before checkDuePeriod() or will the fact that the compiler includes the super() constructor automatically when compiling the class imply the super. call of the methods that class B calls from class A?
I'm a little confused about this. Thanks in advance.
The super class's implementation of regular methods is not automatically invoked in sub classes, but a form of the super class's constructor must be called in a sub class's constructor.
In some cases, the call to super() is implied, such as when the super class has a default (no-parameter) constructor. However, if no default constructor exists in the super class, the sub class's constructors must invoke a super class constructor directly or indirectly.
Default constructor example:
public class A {
public A() {
// default constructor for A
}
}
public class B extends A {
public B() {
super(); // this call is unnecessary; the compiler will add it implicitly
}
}
Super class without default constructor:
public class A {
public A(int i) {
// only constructor present has a single int parameter
}
}
public class B extends A {
public B() {
// will not compile without direct call to super(int)!
super(100);
}
}
If you call checkDuePeriod() in B without super., means you want to invoke the method that belongs to the this instance (represented by this within B) of B. So, it equivalent to saying this.checkDuePeriod(), so it just doesn't make sense for the compiler to add super. in the front.
super. is something that you must explicitly add to tell the compiler that you want to call the A's version of the method (it is required specially in case B has overridden the implementation provided by A for the method).
Call of super() as a default constructor (constructor with no args) can be direct or non direct but it garants that fields of extendable class are properly initialized.
for example:
public class A {
StringBuilder sb;
public A() {
sb = new StringBuilder();
}
}
public class B extends A {
public B() {
//the default constructor is called automatically
}
public void someMethod(){
//sb was not initialized in B class,
//but we can use it, because java garants that it was initialized
//and has non null value
sb.toString();
}
}
But in case of methods:
Methods implement some logic. And if we need to rewrite logic of super class we use
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
//new check goes here
}
}
and if we want just implement some extra check, using the value returned from checkDuePeriod() of superclass we should do something like this
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
if(super.checkDuePeriod()){
//extra check goes here
}else{
//do something else if need
}
return checkResult;
}
}
First about the Constructors:
- When ever an object of a class is created, its constructor is initialized and at that time immediately the constructor of its super-class is called till the Object class,
- In this process all the instance variables are declared and initialized.
- Consider this scenario.
Dog is a sub-class of Canine and Canine is a sub-class of Animal
Now when Dog object is initialized, before the object actually forms, the Canine class object must be form, and before Canine object can form the Animal class object is to be formed, and before that Object class object must be form,
So the sequence of object formed is:
Object ---> Animal ---> Canine ---> Dog
So the Constructor of the Super-Class is Called before the Sub-Class.
Now with the Method:
The most specific version of the method that class is called.
Eg:
public class A{
public void go(){
}
}
class B extends A{
public static void main(String[] args){
new B().go(); // As B has not overridden the go() method of its super class,
// so the super-class implementation of the go() will be working here
}
}

regarding constructors

i was developing the below code....
class P {
//public P(){}
public P(int i) {
}
}
class D extends P {
public D(){ // default constructor must be defined in super class
}
}
public class agf {
public static void main(String[] args) {
}
}
Now in class p explicit parametrized constructor is defined and in class D default constructor is defined but it is still showing the compile time error ,please explain
Your parent Class P explicitly defines a constructor, due to which no-arg constructor will not be added automatically. When you write a no-arg constructor for class D without having a specific constructor call for the class P using super keyword as mentioned below,
Class D extends P {
public D() {
super(10);
}
}
you are instructing it to call the no-arg constructor of P. Since P only has constructor that you defined, it cannot call the no-arg constructor of P.
In simple terms every object of D will have part of P. But it has no idea how to initialize / construct that P part, since it has no no-arg constructor.
In the subclass, if you don't invoke a superclass constructor explicitly, there must be a default superclass constructor that the VM can invoke for you.
In the superclass, if you explicitly define a constructor, the default no-argument constructor is NOT generated by the compiler.
Therefore, in the situation you show, you defined a non-default constructor in the superclass, which prevented the compiler from generating the default no-arg constructor. Then in the subclass, you didn't explicitly invoke a constructor in the superclass. The compiler tried to generate a no-arg superclass constructor call and didn't find a suitable constructor to call.
Inside this constructor:
public D()
{
// no call to super?? implicit call to super()
}
There is an implicit call to the empty constructor of the super class (which doesn't exist in your case)
Either implement an empty constructor in the super class, or call the parameterized constructor explicitly, e.g.:
public D()
{
super(1);
}
I would suggest you read this tutorial as well.
When creating an instance of class D, the constructor of P is first called (since D is also P). The problem is that P's constructor cannot be called since a value has to be provided to it, and that's something you're not currently doing.
To fix that, the first line in D's constructor have to be super(value), while value can be a parameter sent to D's constructor, or..anything else you want (in case you want to leave D's constructor a default one).
You can go through it step-by-step in debug, it can help to clear things out.

Is Constructor Overriding Possible?

What i know is, the compiler writes a default no argument constructor in the byte code. But if we write it ourselves, that constructor is called automatically. Is this phenomena a constructor overriding?
What you describe isn't overriding. If you don't specify a default constructor, the
compiler will create a default constructor. If it's a subclass, it will call
the default parent constructor(super()), it will also initialize all instance variables to
a default value determined by the type's default value(0 for numeric types, false for booleans, or null
for objects).
Overriding happens when a subclass has the same name, number/type of parameters, and
the same return type as an instance method of the superclass. In this case, the subclass
will override the superclass's method. Information on overriding here.
Constructors are not normal methods and they cannot be "overridden". Saying that a constructor can be overridden would imply that a superclass constructor would be visible and could be called to create an instance of a subclass. This isn't true... a subclass doesn't have any constructors by default (except a no-arg constructor if the class it extends has one). It has to explicitly declare any other constructors, and those constructors belong to it and not to its superclass, even if they take the same parameters that the superclass constructors take.
The stuff you mention about default no arg constructors is just an aspect of how constructors work and has nothing to do with overriding.
It is never possible. Constructor Overriding is never possible in Java.
This is because,
Constructor looks like a method but
name should be as class name and no
return value.
Overriding means what we have declared
in Super class, that exactly we have
to declare in Sub class it is called
Overriding. Super class name and Sub
class names are different.
If you trying to write Super class
Constructor in Sub class, then Sub
class will treat that as a method not
constructor because name should
not match with Sub class name. And it
will give an compilation error that
methods does not have return value. So
we should declare as void, then only
it will compile.
Have a look at the following code :
Class One
{
....
One() { // Super Class constructor
....
}
One(int a) { // Super Class Constructor Overloading
....
}
}
Class Two extends One
{
One() { // this is a method not constructor
..... // because name should not match with Class name
}
Two() { // sub class constructor
....
}
Two(int b) { // sub class constructor overloading
....
}
}
You can have many constructors as long as they take in different parameters. But the compiler putting a default constructor in is not called "constructor overriding".
Cannot override constructor. Constructor can be regarded as static, subclass cannot override its super constructor.
Of course, you could call protected-method in super class constructor, then overide it in subclass to change super class constructor. However, many persons suggest not to use the trick, in order to protect super class constructor behavior. For instance, FindBugs will warn you that a constructor calls a non-final method.
No it is not possible to override a constructor. If we try to do this then compiler error will come. And it is never possible in Java. Lets see the example. It will ask please write a return type o the method. means it will treat that overriden constructor as a method not as a constructor.
package com.sample.test;
class Animal{
public static void showMessage()
{
System.out.println("we are in Animal class");
}
}
class Dog extends Animal{
public void DogShow()
{
System.out.println("we are in Dog show class");
}
public static void showMessage()
{
System.out.println("we are in overriddn method of dog class");
}
}
public class AnimalTest {
public static void main(String [] args)
{
Animal animal = new Animal();
animal.showMessage();
Dog dog = new Dog();
dog.DogShow();
Animal animal2 = new Dog();
animal2.showMessage();
}
}
But if we write it ourselves, that
constructor is called automatically.
That's not correct. The no-args constructor is called if you call it, and regardless of whether or not you wrote it yourself. It is also called automatically if you don't code an explicit super(...) call in a derived class.
None of this constitutes constructor overriding. There is no such thing in Java.
There is constructor overloading, i.e. providing different argument sets.
Because a constructor cannot be inherited in Java and Method Overriding requires inheritance. Therefore, it's not applicable.
Constructor overriding is not possible because of following reason.
Constructor name must be the same name of class name. In Inheritance practice you need to create two classes with different names hence two constructors must have different names. So constructor overriding is not possible and that thought not even make sense.
Your example is not an override. Overrides technically occur in a subclass, but in this example the contructor method is replaced in the original class.
Constructor looks like a method but name should be as class name and no return value.
Overriding means what we have declared in Super class, that exactly we have to declare in Sub class it is called Overriding. Super class name and Sub class names are different.
If you trying to write Super class Constructor in Sub class, then Sub class will treat that as a method not constructor because name should not match with Sub class name. And it will give an compilation error that methods does not have return value. So we should declare as void, then only it will compile.
It should also be noted that you can't override the constructor in the subclass with the constructor of the superclass's name. The rule of OOPS tells that a constructor should have name as its class name. If we try to override the superclass constructor it will be seen as an unknown method without a return type.
While others have pointed out it is not possible to override constructors syntactically, I would like to also point out, it would be conceptually bad to do so. Say the superclass is a dog object, and the subclass is a Husky object. The dog object has properties such as "4 legs", "sharp nose", if "override" means erasing dog and replacing it with Husky then Husky would be missing these properties and be a broken object. Husky never had those properties and simply inherited them from dog.
On the other hand, if you intend to give Husky everything that dog has, then conceptually you could "override" dog with Husky, but there would be no point in creating a class that is the same as dog, it's not practically an inherited class but a complete replacement.
method overriding in java is used to improve the recent code performance written previously .
some code like shows that here we are creating reference of base class and creating phyisical instance of the derived class.
in constructors overloading is possible.
InputStream fis=new FileInputStream("a.txt");
int size=fis.available();
size will return the total number of bytes possible in a.txt
so
I found this as a good example for this question:
class Publication {
private String title;
public Publication(String title) {
this.title = title;
}
public String getDetails() {
return "title=\"" + title + "\"";
}
}
class Newspaper extends Publication {
private String source;
public Newspaper(String title, String source) {
super(title);
this.source = source;
}
#Override
public String getDetails() {
return super.getDetails() + ", source=\"" + source + "\"";
}
}
class Article extends Publication {
private String author;
public Article(String title, String author) {
super(title);
this.author = author;
}
#Override
public String getDetails() {
return super.getDetails() + ", author=\"" + author + "\"";
}
}
class Announcement extends Publication {
private int daysToExpire;
public Announcement(String title, int daysToExpire) {
super(title);
this.daysToExpire = daysToExpire;
}
#Override
public String getDetails() {
return super.getDetails() + ", daysToExpire=" + daysToExpire;
}
}

Categories

Resources