Skip to main content

9. Reference Variable and Constructor

 

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).
  • class ShellClass{
        public static void main(String[] args) {
            ShellClass refVar;
            Object refVar;
        }
    }

  • 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.
  • 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);
        }
    }

  • The reference variable's type (not the object's type), determines which methods can be called.
  • 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
        }
    }

  • 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.

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.
  • class A {
    }
  • If we've typed in a constructor with arguments, we won't have an no-args constructor unless we type it in ourself.
  • class A {
        A(int a) {
        }
    }
  • 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.
  • class A {
        A() {
        }

        A(int a) {
        }

        A(int a, int b) {
        }
    }
  • 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().
  • class B {
        B() {
            super();
        }

        B(int b) {
            this();
        }

        B(int a, int b) {
            this(b);
        }
    }
  • 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.

Default Constructor

  • The default constructor has the same access modifier as the class.
  • public class Main {
    }
  • The default constructor has no arguments.
  • The default constructor includes a no-arg call to the super constructor (super()).
  • class A {
        A() {
            System.out.println("A class constructor...");
        }
    }

    class B extends A {
        public static void main(String[] args) {
            new B();
        }
    }

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();
    }
}
  1. 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.
  2. Animal constructor is invoked (Animal is the superclass of Dog).
  3. Object constructor is invoked (Object is the ultimate superclass of all classes).
  4. Object instance variables are given their explicit values.
  5. Object constructor completes.
  6. Animal instance variables are given their explicit values (if any).
  7. Animal constructor completes.
  8. Dog instance variables are given their explicit values (if any).
  9. Dog constructor completes.
Prev Next

Comments