Difference between 'super' and 'this' [duplicate] - java

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
this and super in java
I'm new to development. Something that I'm still unable to understand is the difference between this and super keywords. If there are any answers, it would be highly appreciated. Thanks.

this
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
super
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged).

super refers to the base class that the current class extends. this refers to the current class instance.
So, if Parent extends Child and you create a new Child(), super refers to the Parent class (and doing something like super() in the constructor would call the parent's constructor) and this refers to the actual Child instance you created with new.

Super refers to the superclass that a class extends. this refers to the current instance of a class.

These concepts can be confusing for new developers, they will be more clear when you learn about extending classes (inheritance). Sometimes when you refer to a variable or method, you might be being ambiguous for example if you repeated a class variable name in a method, the compiler won't know which variable you are referring to, so you can use this to specify you are referring to the current class's variable (not the local variable). The following would be ambiguous (and WRONG):
class Bike
{
int speed = 10;
public setSpeed(int speed)
{
speed = speed;
}
}
The compiler would have no idea what you intended, and will probably insult you with a cryptic (for a new developer) error message. Using this in the following way tells the compiler "I am referring to the class level variable, NOT the method level variable"
class Bike
{
int speed = 10;
//Constructors and shiz
public void setSpeed(int speed)
{
this.speed = speed;
}
}
(Although in practice you shouldn't duplicate variable names in this way!)
So to summarise, this tells the compiler that you're referring to the CURRENT class. Further ambiguity can arise when you extend classes (inherit functionality for a parent or super class), because the option of overriding the parent method arrises.
class Bike
{
public Bike()
{}
public void printSpeed()
{
System.out.println("This generic bike can go 10 m/s!!");
}
}
Now if we were to extend the bike class by introducing a more specific type of bike, we may want to override the printSpeed method to give the speed of our shiny new bike, like so:
class MountainBike extends Bike
{
public MountainBike() {}
public void printSpeed()
{
System.out.println("WHOAAAH!! MOUNTAIN BIKE GOES 100 m/s!!");
}
public void printGenericSpeed()
{
super.printSpeed();
}
}
The super.printSpeed() tells the compiler to run this method from the parent class, so a call to super.printSpeed() would actually call the printSpeed() method in the Bike class. The following code:
public static void main(String args[])
{
MountainBike mb = new MountainBike();
mb.printSpeed();
mb.printGenericSpeed();
}
will print
WHOAAAH!! MOUNTAIN BIKE GOES 100 m/s!!
This bike can go 10 m/s!!
Note that if we had not overridden the printSpeed() method, calling the following would be a call to the printSpeed() method of the Bike class.
public static void main(String args[])
{
MountainBike mb = new MountainBike();
mb.printSpeed();
}
would print
This bike can go 10 m/s!!
So to conclude, we use this to refer to the current class we're in, and super to refer to the parent of the class we're in.

In Java the keyword this refers to the current object of a class, like in:
class Point {
public int x = 0;
public int y = 0;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return x + "," + y;
}
}
class Point3D extends Point {
public int z = 0;
public Point(int x, int y, int z) {
super(x,y);
this.z = z;
}
public String toString() {
return super.toString() + "," + z;
}
}
In the constructor of the class Point this.x refers to the x defined in the class, where x is the parameter passed into the constructor. Here this is used to resolve the ambiguity of the name x. The same thing is true for y.
In the class Point3D the method toString() uses the return value of the super class Point to produce its own return value.

this: is the reference to the current object in the methods of its class. Refer to any member of the current object through the this keyword.
super: is the derived class' parent when your class extends it through the extend keyword, and you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a protected fields.

this keyword refers to the current instance at that point in time.
super keyword refers to the parent/super class of the current class.
EX:
class Test
{
Test()
{
}
Test(int i)
{
System.out.println("i=" + i);
}
}
class Sample extends Test
{
int i;
void Sample(int i) //constructor
{
this.i=i; // referring class version of the i using 'this'
super(i); // passing parameter to Super/Parent class constructor.
}
}

Related

Share a variable between functions in implementation of a interface

Consider an interface and its implementation,
interface A {
int a;
default void add() {
a = a+10;
}
public void sub();
}
class X implements A {
public sub() {
a = a-5;
}
}
I have to use the variable a in sub() function of class X. How can I do?
All variables declared inside interface are implicitly public static final variables(constants).
From the Java interface design FAQ by Philip Shaw:
Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
Since interface doesn't have a direct object, the only way to access them is by using a class/interface and hence that is why if interface variable exists, it should be static otherwise it wont be accessible at all to outside world. Now since it is static, it can hold only one value and any classes that implements it can change it and hence it will be all mess.
Hence if at all there is an interface variable, it will be implicitly static, final and obviously public!!!
The field a in the interface A always final and static and it isn't supposed to be modified in any way including reassigning it in an instance method.
Interfaces don't have the state. Abstract classes may.
abstract class A {
protected int a;
public void add() {
a += 10;
}
public abstract void sub();
}
final class X extends A {
public void sub() {
a -= 5;
}
}
I would use an abstract class instead of an interface. That way the variable can be modified by the extending class.
abstract class A{
int a=10;
void add(){
a=a+10;
}
public abstract void sub();
}
class X extends A{
public void sub(){
a=a-5;
}
}
Yes, We can use abstract class.
Since in interface variables declared are by default final.
Code with Interface
Code with Abstract Class

why protected constructor can't be called in child class in another package? Am I right about my logic? [duplicate]

Why can't we instantiate a class with a protected constructor if its child is in a different package? If protected variables and methods can be accessed, why doesn't the same rule also apply for a protected constructor?
pack1:
package pack1;
public class A {
private int a;
protected int b;
public int c;
protected A() {
a = 10;
b = 20;
c = 30;
}
}
pack2:
package pack2;
import pack1.A;
class B extends A {
public void test() {
A obj = new A(); // gives compilation error; why?
//System.out.println("print private not possible :" + a);
System.out.println("print protected possible :" + b);
System.out.println("print public possible :" + c);
}
}
class C {
public static void main(String args[]) {
A a = new A(); // gives compilation error; why?
B b = new B();
b.test();
}
}
According to the Java Spec (https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.2)
6.6.2.2. Qualified Access to a protected Constructor
Let C be the class in which a protected constructor is declared and let S be the innermost class in whose declaration the use of the protected constructor occurs. Then:
If the access is by a superclass constructor invocation super(...), or a qualified superclass constructor invocation E.super(...), where E is a Primary expression, then the access is permitted.
If the access is by an anonymous class instance creation expression new C(...){...}, or a qualified anonymous class instance creation expression E.new C(...){...}, where E is a Primary expression, then the access is permitted.
If the access is by a simple class instance creation expression new C(...), or a qualified class instance creation expression E.new C(...), where E is a Primary expression, or a method reference expression C :: new, where C is a ClassType, then the access is not permitted. A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) or a method reference expression only from within the package in which it is defined.
In your case, access to the protected constructor of A from B would be legal from a constructor of B through an invocation of super(). However, access using new is not legal.
JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package...
6.6.7 Example: protected Fields, Methods, and Constructors Consider
this example, where the points package
declares:
package points;
public class Point {
protected int x, y;
void warp(threePoint.Point3d a) {
if (a.z > 0) // compile-time error: cannot access a.z
a.delta(this);
}
}
and the threePoint package declares:
package threePoint;
import points.Point;
public class Point3d extends Point {
protected int z;
public void delta(Point p) {
p.x += this.x; // compile-time error: cannot access p.x
p.y += this.y; // compile-time error: cannot access p.y
}
public void delta3d(Point3d q) {
q.x += this.x;
q.y += this.y;
q.z += this.z;
}
}
which defines a class Point3d. A
compile-time error occurs in the
method delta here: it cannot access
the protected members x and y of its
parameter p, because while Point3d
(the class in which the references to
fields x and y occur) is a subclass of
Point (the class in which x and y are
declared), it is not involved in the
implementation of a Point (the type of
the parameter p). The method delta3d
can access the protected members of
its parameter q, because the class
Point3d is a subclass of Point and is
involved in the implementation of a
Point3d. The method delta could try to
cast (§5.5, §15.16) its parameter to
be a Point3d, but this cast would
fail, causing an exception, if the
class of p at run time were not
Point3d.
A compile-time error also occurs in
the method warp: it cannot access the
protected member z of its parameter a,
because while the class Point (the
class in which the reference to field
z occurs) is involved in the
implementation of a Point3d (the type
of the parameter a), it is not a
subclass of Point3d (the class in
which z is declared).
I agree with previous posters, don't know why you would want to do this (instantiate parent in that way in extending class) but you could even do something like this:
public void test() {
A obj = new A(){}; // no compilation error; why? you use anonymous class 'override'
...
Why do you need A obj=new A(); in class, whereas object of class b is itself an object of class A
And in class c it is giving error because, you are accessing the protected property of class A which is constructor.
To get object of class A in this case you must use this function in class A
static A getInstance()
{
A obj = new A(); // create obj of type A.
return obj; // returns that object by this method. No need to use 'New' kind of instantiation.
}
If protected variables and methods can be accessed, why doesn't the same rule also apply for a protected constructor?
Protected variables and methods can only be accessed if the child class in another package extends the class containing the protected variables and methods.
You are able to access variable 'b' in child class B because you have extended the class A. You will not be able to access variable 'b' in class C as it is not extending class A.
The only way to access protected constructor in child class is by using parent class reference variable and child class object.
package pack2;
import pack1.A;
class B extends A {
public void test() {
A obj = new B(); // will execute protected constructor
System.out.println("print protected possible :" + b);
}
}

Constructor with and without any statement

Sometimes in a constructor, no statement is given. What does that indicate? For example if i create a class CIRCLE, then inside the class i write CIRCLE() {}, that is nothing is written inside. Can anyone explain it?
If your question is "why would anyone write such a constructor", then the answer is that the no-args default constructor only exists if no other constructor is specified.
Consider the following class.
class Foo {
int x;
}
As written, someone could write the following code to construct Foo.
Foo foo = new Foo();
However, now suppose I added a constructor which takes arguments.
class Foo {
int x;
public Foo(int x) {
this.x = x;
}
}
Now, suddenly, Foo foo = new Foo(); no longer works. To restore it, I must add the empty constructor again.
class Foo {
int x;
public Foo(int x) {
this.x = x;
}
public Foo() { }
}
Now, What if there are no other constructors that take arguments?
In that case, it is generally as the other answers suggest, to restrict access to constructing the class.
In the following definition of Foo, nobody is allowed to construct Foo. Perhaps Foo is meant only as a static class.
class Foo {
int x;
private Foo() { }
}
In the protected case, only subclasses can construct Foo.
class Foo {
int x;
protected Foo() { }
}
If there is no code in the constructor, chances are, it was declared to change the access to the constructor. By default, constructors are public. If you wanted to make it private, protected or package-private, you must explicitly declare it and manually change the modifier.
class Example {
public static void main(String[] args) {
new Demo(); //this is currently allowed
}
}
class Demo {
}
In order to prevent the creation of a Demo object within Example, we could declare Demo's constructor amd make it private:
class Demo {
private Demo() { }
}
Another reason could be that the class has a constructor that requires parameters. If so, you must explicitly declare the no-arg constructor to be able to use it.
If nothing is written, then when a new Object of that type is created, nothing 'extra' is done, whereas if in the constructor has code in, it does something.
For example, the following consructor for a class called 'Bank' assigns the argument 'name' to the field 'bankName', then instantiates a Terminal and 2 bank accounts:
private static final int INITIAL_BALANCE = 200;
public Bank( String name )
{
bankName = name;
atm = new Terminal();
account1 = new BankAccount( INITIAL_BALANCE );
account2 = new BankAccount( INITIAL_BALANCE );
}
It's a default constructor. For instance if you go:
Circle circle = new Circle();
You are then calling the default constructor. When you go ... Circle() that is a call to the default constructor, the one with no parameters.
The point of this is just to 'construct' an object or instantiate a class (instantiate just means create an object which is an instance of the class) with no additional information i.e. parameters.
This would generally be used to initialize fields to their default values, like so:
public Circle() {
this.x = 0;
this.y = 0;
}

Why variable which didn't exactly declare equals to 0?

Please sorry me for that newbie question. This is for my so strange, because before java coding, I have had a C++ background, where variable by default is equal to undefined or null;
So I have a abstract class:
public abstract class Animal {
int lifeBar;
public void eat(int x) {
lifeBar += x;
}
}
And I have Bird class which extends it:
public class Bird extends Animal {
}
And Main class:
public class Main {
public static void main(String[] args) {
Animal bird = new Bird();
bird.eat(10);
System.out.println("bird: " + bird.lifeBar);
}
}
I thought that there should be compilation error, because I didn't declare lifeBar variable, but the console showed me 10. Why is that? Is it because there some default constructor?
Inheritance means subclasses can extends the state of superclass
hence in your example, when Bird extends Animal all the methods and
variables are inherited in Bird class.
lifeBar is an instance variable of type int hence its default value is 0
YOu are calling the method in which lifeBar += x; statement increments the value by 10 because you are passing 10 as argument to method.
lifeBar is member of Animal which isn't initialized explicitly, so it sets its default value that is 0 for int
See
default value of different types

Confused with this simple example of polymorphism

Please have a look at this code :
class Foo {
public int a;
public Foo() {
a = 3;
}
public void addFive() {
a += 5;
}
public int getA() {
System.out.println("we are here in base class!");
return a;
}
}
public class Polymorphism extends Foo{
public int a;
public Poylmorphism() {
a = 5;
}
public void addFive() {
System.out.println("we are here !" + a);
a += 5;
}
public int getA() {
System.out.println("we are here in sub class!");
return a;
}
public static void main(String [] main) {
Foo f = new Polymorphism();
f.addFive();
System.out.println(f.getA());
System.out.println(f.a);
}
}
Here we assign reference of object of class Polymorphism to variable of type Foo, classic polmorphism. Now we call method addFive which has been overridden in class Polymorphism. Then we print the variable value from a getter method which also has been overridden in class Polymorphism. So we get answer as 10. But when public variable a is SOP'ed we get answer 3!!
How did this happen? Even though reference variable type was Foo but it was referring to object of Polymorphism class. So why did accessing f.a not result into value of a in the class Polymorphism getting printed? Please help
You're hiding the a of Polymorphism - you should actually get a compiler warning for that. Therefore those are two distinct a fields. In contrast to methods fields cannot be virtual. Good practice is not to have public fields at all, but only methods for mutating private state (encapsulation).
If you want to make it virtual, you need to make it as a property with accessor methods (e.g. what you have: getA).
This is due to the fact that you can't override class varibles. When accessing a class variable, type of the reference, rather than the type of the object, is what decides what you will get.
If you remove the redeclaration of a in the subclass, then I assume that behaviour will be more as expected.

Categories