Constructors & "this"

A Constructor's Job

A constructor's only job is to put a new object into a valid state — every instance variable set to something usable. Its signature looks like a method's, but with two differences: no return type (not even void), and its name is always exactly the class's name.

public class Climber
{
    private int motorPort;

    public Climber(int motorPort) // same name as the class, no return type
    {
        this.motorPort = motorPort;
    }
}

The Default Constructor

Every instance variable starts at its type's default the instant an object exists — 0 for int, 0.0 for double, false for boolean, null for any reference type — whether or not you ever write a constructor. If you don't write any constructor at all, Java adds an empty no-argument one for you; it doesn't do anything beyond that automatic default-initialization. The moment you write even one constructor yourself, that free one disappears — you have to cover every way you want objects of your class to be built.

public class Climber
{
    private int motorPort; // if no constructor is written, this defaults to 0
}

Overloaded Constructors

Just like methods (Ch.4.1), a class can have several constructors, distinguished by their parameter lists — this is the same overloading concept:

public class Climber
{
    private int motorPort;
    private double climbSpeed;

    public Climber(int motorPort)
    {
        this.motorPort = motorPort;
        this.climbSpeed = 0.5; // a sensible default
    }

    public Climber(int motorPort, double climbSpeed)
    {
        this.motorPort = motorPort;
        this.climbSpeed = climbSpeed;
    }
}

Chaining Constructors with this(...)

The two Climber constructors above duplicate the this.motorPort = motorPort; line. When one constructor's job is really "do what another constructor does, plus a little more," it can call that other constructor directly with this(...) instead of repeating its body:

public class Climber
{
    private int motorPort;
    private double climbSpeed;

    public Climber(int motorPort)
    {
        this(motorPort, 0.5); // delegates to the two-argument constructor below
    }

    public Climber(int motorPort, double climbSpeed)
    {
        this.motorPort = motorPort;
        this.climbSpeed = climbSpeed;
    }
}

On Java 17, a this(...) call must be the very first statement in the constructor — nothing can come before it, not even a simple argument check. Java 25 (JEP 513, Flexible Constructor Bodies) relaxes this: statements can now run before this(...), as long as they don't touch the new object's fields or call its methods yet (validating an argument, for example, is fine). This lesson still puts this(...) first, which works unchanged on both versions.

this: Referring to the Current Object

Inside an instance method or constructor, this refers to the specific object the method/constructor is currently running for. It's most useful when a parameter shares a name with an instance variable — this.motorPort unambiguously means "this object's motorPort," while bare motorPort means the parameter:

public Climber(int motorPort)
{
    this.motorPort = motorPort; // left side: instance variable. right side: parameter.
}

Without this, motorPort = motorPort; would just assign the parameter to itself — the instance variable would never actually get set.

this only exists inside instance methods and constructors — a static method has no current object to refer to, so it has no this (Ch.7.4).

this as an Argument

this is a real reference, usable anywhere an object reference is expected — including passing the current object into another method or constructor:

public class Climber
{
    private double currentHeight;

    public void reportTo(ClimbLogger logger)
    {
        logger.record(this); // pass the current Climber object itself
    }
}

Common Pitfalls

  • Forgetting this when a parameter shadows an instance variable — the general scope/lifetime rule behind this is Ch.7.2's "Where Variables Live." motorPort = motorPort; (no this) does nothing useful — it assigns the parameter to itself, leaving the actual instance variable untouched.
  • Assuming a class always gets a free default constructor. Only true if you write zero constructors yourself. Write even one, and you're responsible for every constructor your class needs.
  • Writing void Climber(...) instead of a constructor. Adding a return type — even void — makes it an ordinary method that just happens to share the class's name, not a constructor. It never runs automatically when you new the class; Java still builds the object with whichever real constructor exists (or the free default one, if you wrote none).

Key Takeaways

  • A constructor's signature has no return type and always matches the class's name; its job is to leave the object in a valid state.
  • Every instance variable starts at its type's default regardless of any constructor; with no constructor written, Java adds an empty default one — writing any constructor yourself removes it.
  • Constructors can be overloaded, just like methods, distinguished by parameter lists; one overload can delegate to another with this(...) instead of repeating setup code (first statement on Java 17; Java 25 also allows validation before it, JEP 513).
  • this refers to the current object inside an instance method or constructor — essential for disambiguating a parameter from an instance variable of the same name (shadowing, Ch.7.2).
  • this can be passed as an argument, like any other object reference. Static methods have no this.

Deck context: mechacoder-test/src/lessons/java-1.js, slide 8 ("CONSTRUCTORS")