Reference Variable
- A reference variable can be of only one type, and once declared, that type can never be changed (although the object it references can change).
- A reference is a variable, so it can be reassigned to other objects (unless the reference is declared final).
- A reference variable can refer to any object of the same type as the declared reference, or it can refer to any subtype of the declared type.
- The reference variable's type (not the object's type), determines which methods can be called.
- A reference variable can be declared as a class type or an interface type. If the variable is declared as an interface type, it can reference any object of any class that implements the interface.
class ShellClass{
public static void main(String[] args) {
ShellClass refVar;
Object refVar;
}
}
class ShellClass {
public static void main(String[] args) {
Object refVar1 = new ShellClass();
Object refVar2 = new Object();
System.out.println("refVar1: " + refVar1 + "\trefVar2: " + refVar2);
refVar2 = refVar1;
System.out.println("refVar1: " + refVar1 + "\trefVar2: " + refVar2);
}
}
class A {
void funcA() {
}
}
class B extends A {
void funcB() {
}
}
class ShellClass {
public static void main(String[] args) {
A refVar = new B();
refVar.funcA(); // OK
refVar.funcB(); // Error
}
}
Downcasting
- If we have a reference variable that refers to a subtype object, we can assign it to a reference variable of the subtype.
- We must make an explicit cast to do this.
- We can access the subtype's members with this new reference variable.
class Animal {
void makeNoise() {
System.out.println("Generic noise");
}
}
class Dog extends Animal {
@Override
void makeNoise() {
System.out.println("Bark");
}
void playDead() {
System.out.println("Roll over");
}
}
class ShellClass {
public static void main(String[] args) {
Animal a = new Dog();
if (a instanceof Dog) {
Dog dog = (Dog) a; // Downcasting the reference variable (a)
dog.playDead();
}
}
}
Upcasting
- We can assign a reference variable to a supertype reference variable explicitly or implicitly.
- This is an inherently safe operation because the assignment restricts the access capabilities of the new variable.
class Animal {
void makeNoise() {
System.out.println("Generic noise");
}
}
class Dog extends Animal {
@Override
void makeNoise() {
System.out.println("Bark");
}
void playDead() {
System.out.println("Roll over");
}
}
class ShellClass {
public static void main(String[] args) {
Dog dog = new Dog();
Animal a2 = dog; // Upcasting the reference variable implicitly
Animal a3 = (Animal) dog; // Upcasting the reference variable explicitly
}
}
Constructor
- Objects are constructed. We can't make a new object without invoking a constructor.
- Constructors are the code that runs whenever we use the keyword new.
- We can't make a new object without invoking not just the constructor of the object's actual class type, but also the constructor of each of its superclass.
- Typically, constructors are used to initialize instance variable state.
Rules for Constructors
- Every class, including abstract classes, must have a constructor. Although if we don't create one explicitly, a default constructor will be automatically generated by the compiler.
- If we've typed in a constructor with arguments, we won't have an no-args constructor unless we type it in ourself.
- Constructors have no return type and their names must exactly match the class name.
- Constructors are never inherited, thus they cannot be overridden. But constructors can be overloaded and the argument list determines which overloaded constructor is called.
- Constructors can't be marked static, final or abstract.
- It's legal (but stupid) to have a method with the same name as the class, but that doesn't make it a constructor.
- The first line in a constructor must be a call to super() or a call to this().
- If a constructor has a call to this(), the compiler knows that the constructor will not be the one to invoke super().
- Abstract classes have constructors that are called when a concrete subclass is instantiated.
- Interfaces do not have constructors.
class B {
B() {
super();
}
B(int b) {
this();
}
B(int a, int b) {
this(b);
}
}
Default Constructor
- The default constructor has the same access modifier as the class.
- The default constructor has no arguments.
- The default constructor includes a no-arg call to the super constructor (super()).
public class Main {
}
Constructor chaining
We know that constructors are invoked at runtime when we say new on some class type as follows:
class Animal {
}
class Dog extends Animal {
}
class ShellClass {
public static void main(String[] args) {
new Dog();
}
}
- Dog constructor is invoked. Every constructor invokes the constructor of its superclass with an (implicit) call to super(), unless the constructor invokes an overloaded constructor of the same class.
- Animal constructor is invoked (Animal is the superclass of Dog).
- Object constructor is invoked (Object is the ultimate superclass of all classes).
- Object instance variables are given their explicit values.
- Object constructor completes.
- Animal instance variables are given their explicit values (if any).
- Animal constructor completes.
- Dog instance variables are given their explicit values (if any).
- Dog constructor completes.
Comments
Post a Comment