Construction & this

Once you understand that objects have identity and state, the next question is how they are born safely. Construction is where an object moves from a description into a valid runtime instance, and this is the pointer that lets the object refer to itself during that process.

Blueprint vs. Instance Allocation

A class is the blueprint. It defines field order, type expectations, constructor signatures, and method dispatch metadata. It does not hold per-object state by itself.

An object is the allocated instance. When new Movie(...) runs, the runtime reserves space for the object header, field slots, and hidden metadata such as a class pointer or vtable pointer. The returned variable does not contain the full object; it contains an address-like reference to that heap allocation.

For primitive fields, default initialization writes type-specific zero values: 0, 0.0, false, or equivalent. For reference fields, default initialization writes null, because the runtime has no nested object address until one is explicitly assigned.

Constructor Lifecycle

Constructors are controlled entry points into valid object state.

Default or no-arg constructors create a valid instance without caller-supplied state. If the class does not define any constructor, many languages synthesize one. If fields are not explicitly assigned, default values remain in their slots.

Parameterized constructors bind runtime arguments into instance fields before exposing the reference. This matters because it prevents client code from observing a partially initialized object.

Copy constructors define how identity and ownership should move from one object to another. A shallow copy duplicates field values exactly, including nested reference addresses. A deep copy recursively allocates new nested objects so mutation through the copy cannot corrupt the original.

Private constructors move allocation authority away from external callers. This is useful when you want a static gatekeeper such as getInstance() to decide when the object may be allocated and which reference all callers receive.

The Current Object Pointer

Inside a non-static method, this is the implicit reference to the current object. It is passed into instance method calls by the runtime, even when it is not visible in the method signature.

this resolves collisions between parameter names and field names:

class Movie {
  private String title;

  Movie(String title) {
    this.title = title;
  }
}

It also enables constructor chaining and fluent APIs. Returning this returns the same live receiver object, allowing method chains like builder.setName("x").setRuntime(120).

Static methods do not have this, because they bind to the class definition rather than a particular heap instance.

Lab 2.1: The Reference Memory Leak

This lab starts with a Movie object that owns a mutable nested Cast structure. The initial code aliases copyMovie to originalMovie, so both variables point to the same heap object. Run the engine first to see the corruption, then add a deep-copy constructor that duplicates the nested cast member array.

Memory Layout & Reference Inspector

Exercise 2.1: Copy Constructor Basics

Pattern-based checker only — it inspects code shape and state flow, but it does not compile Java.

Engine idle

Replace aliasing with a copy constructor so the new object gets its own identity.

Pointer Matrix
0x004FFA0originalMovie: Movie -> 0x004FFA0
0x004FFA0+8title_ptr: "Heat"
0x004FFC0copyMovie: uninspected
Execution Trace
  1. Edit the code, then run the inspector.

Lab 2.2: Constructing the Singleton Guard

The unsafe version of ConfigRegistry can allocate two objects when two threads observe instance == null at the same time. Secure it by hiding the constructor and implementing double-checked locking with a volatile static reference.

Concurrent Allocation Guard

Exercise 2.2: Singleton Basics

Pattern-based checker only — it inspects code shape and state flow, but it does not compile Java.

Engine idle

Hide raw construction and make every call return the same shared instance.

Pointer Matrix
T1Thread 1: instance == null
T2Thread 2: instance == null
heapAllocations: unlocked
Execution Trace
  1. Edit the code, then run the inspector.