7.1 Defining Classes and Instantiating Objects

Key Takeaways

  • A class serves as a compile-time blueprint defining state (fields) and behavior (methods), whereas an object is a dynamic runtime instance allocated on the Java heap.
  • The new operator allocates memory on the Java heap, initializes instance variables to their language default values, executes the constructor, and returns the heap memory address.
  • Stack memory stores method call frames and reference variables holding memory addresses, while heap memory stores the actual object instances and their instance variables.
  • Assigning one reference variable to another copies the reference address (aliasing), meaning both variables point to the identical object on the heap.
  • An object becomes eligible for Garbage Collection (GC) the moment it can no longer be reached from any active GC root, including groups of objects in an island of isolation.
Last updated: September 2026

7.1 Defining Classes and Instantiating Objects

[!NOTE] Exam Focus: Oracle's "Classes and Constructors" topic area carries seven objectives — more than any other topic on the 1Z0-811 outline — starting with "create a new class including a main method" and "describe the relationship between an object and its members". Candidates must master the architectural distinction between class blueprints and runtime objects, the physical mechanics of stack-based reference variables versus heap-allocated instances, member access via the dot operator, reference aliasing, default field initialization, and the exact lifecycle stages that render an object eligible for automatic Garbage Collection (GC).

Java is fundamentally an Object-Oriented Programming (OOP) language. While procedural programming languages (such as C) organize software around sequential procedures and standalone functions that process detached data, the object-oriented paradigm models software as a collection of cooperating objects. Each object encapsulates both its internal state (the data attributes it stores) and its public behavior (the operations and algorithms it can execute).


1. Classes vs. Objects: The Blueprint and the Instance

The relationship between a class and an object is one of the most fundamental concepts tested on the 1Z0-811 examination:

  • Class (The Blueprint): A class is a programmer-defined blueprint, template, or prototype from which individual objects are created. Written in .java source files and compiled into .class bytecode files, a class defines the structure of data (fields) and operations (methods). A class exists as static metadata loaded into the JVM's Metaspace memory area. By itself, a class allocates no dynamic heap memory for application data.
  • Object (The Instance): An object is a concrete, physical instance of a class created at runtime. When an object is instantiated, the Java Virtual Machine (JVM) dynamically allocates a dedicated block of memory on the Java Heap to hold that specific object's data.

The Real-World Architectural Analogy

Consider an architectural blueprint for a modern residence. The blueprint specifies dimensions, room counts, and electrical circuitry, but you cannot live inside a blueprint. To inhabit the home, builders must use the blueprint to construct an actual physical house. From a single blueprint, builders can construct dozens of distinct physical houses. Each house occupies its own physical plot of land, can be painted a different color, and can be modified independently of the other houses. In Java, the blueprint is the class, while each constructed house is an object.

Declaring a Java Class

A minimal Java class definition begins with the class keyword followed by the class identifier:

public class Car {
    // Class body enclosed in curly braces
}

Standard Java naming conventions dictate that class identifiers use UpperCamelCase (also known as PascalCase), beginning with an uppercase letter (BankAccount, OrderProcessor). Under standard Java compilation rules, if a class is declared public, the source file name must match the class name identically, including case (Car.java).


2. Anatomy of a Class: State (Fields) and Behavior (Methods)

A Java class bundles two essential software components together:

public class Car {
    // 1. STATE: Instance Variables (Fields / Attributes)
    String make;
    String model;
    int year;
    double mileage;
    boolean isRunning;

    // 2. BEHAVIOR: Instance Methods
    public void startEngine() {
        isRunning = true;
        System.out.println("Engine started.");
    }

    public void drive(double distance) {
        if (isRunning) {
            mileage += distance;
            System.out.println("Drove " + distance + " miles. Total: " + mileage);
        } else {
            System.out.println("Cannot drive: start engine first!");
        }
    }
}

State: Instance Variables

Instance variables (often called fields or attributes) represent the data held by an individual object instance. Crucially, every instantiated object possesses its own independent copy of instance variables. If your program instantiates three distinct Car objects, three separate mileage variables exist across heap memory.

Default Initialization of Instance Variables

Unlike local variables declared inside method bodies (which contain no default values and must be explicitly initialized before being read), instance variables are automatically initialized to language default values upon heap allocation:

Data Type CategorySpecific Java TypeDefault Value
Integer Primitivesbyte, short, int, long0 (or 0L for long)
Floating-Point Primitivesfloat, double0.0f / 0.0d (0.0)
Character Primitivechar'\u0000' (null character, integer 0)
Boolean Primitivebooleanfalse
Reference TypesAny Class, Interface, Array (String, Car, int[])null

Instance Variables vs. Local Variables

The 1Z0-811 examination frequently tests candidate awareness of the differences between instance fields and local variables:

  • Instance Variables: Declared inside the class body but outside any method, constructor, or block. Allocated on the heap as part of the object. Born when the object is instantiated via new; destroyed when the object is garbage collected. Automatically receive default values.
  • Local Variables: Declared inside a method, constructor, or block (including method parameters). Allocated on the thread stack. Born when the enclosing block is entered; destroyed when the block exits. Never receive default values. Attempting to read an uninitialized local variable results in a fatal compile-time error (variable x might not have been initialized).

Behavior: Instance Methods

Instance methods define the operations that can be performed on or by an object. Instance methods have direct access to the object's instance fields, allowing them to inspect, compute, and mutate the object's internal state over time.


3. Instantiating Objects with the new Operator

Creating an object in Java is known as instantiation. Instantiation involves three distinct syntactic and operational steps:

Car        myCar        =        new           Car();
\_______/  \_______/            \_______/     \_______/
  Type      1. Declaration        2. Instantiation  3. Initialization
(reference  (stack slot for       (allocates heap   (constructor runs
  type)      the pointer)          memory)           on the new object)
  1. Declaration: Car myCar; declares a reference variable named myCar of type Car. This statement allocates a variable slot on the JVM Thread Stack, but creates no object on the heap. At this stage, myCar holds the value null (or is uninitialized if declared as a local variable).
  2. Instantiation: The new keyword is an operator that commands the JVM to dynamically allocate a new block of physical memory on the Java Heap. The JVM calculates the exact byte size required for all instance variables declared by Car (and its superclasses) and zero-initializes that memory block.
  3. Initialization: The constructor invocation Car() immediately follows the new operator. The constructor executes to initialize the newly allocated object's state.
  4. Assignment: The new expression evaluates to the memory reference address of the freshly allocated heap object. The assignment operator (=) stores that address into the stack reference variable myCar.

The Dot Operator (.)

Once a reference variable points to a valid object on the heap, you interact with the object using the member access operator, commonly known as the dot operator (.):

Car myCar = new Car();

// Accessing fields (reading and writing)
myCar.make = "Toyota";
myCar.year = 2024;
System.out.println("Vehicle Year: " + myCar.year);

// Invoking instance methods
myCar.startEngine();
myCar.drive(45.5);

If you attempt to apply the dot operator to a reference variable that holds null (e.g., Car emptyCar = null; emptyCar.startEngine();), the JVM throws a runtime NullPointerException.


4. Stack vs. Heap: Reference Variables vs. Heap Objects

Understanding the runtime memory separation between the JVM Stack and the Java Heap is critical for 1Z0-811 candidates:

AttributeJVM Stack MemoryJava Heap Memory
Primary RoleStores active thread call frames, local primitives, and reference variablesStores all instantiated objects and array instances
LifecycleAutomatic; allocated when a method is entered, popped when the method returnsManaged dynamically; persists as long as reachable from a live GC root
Storage ContentPrimitive values (e.g., int x = 5;) or memory addresses (e.g., 0x7A4F)Actual object instance variables and object metadata headers
Thread AccessPrivate to each individual executing threadShared globally across all threads in the JVM process
Allocation SpeedExtremely fast pointer adjustmentsDynamic memory allocation managed by the JVM allocator
Default ValuesNone for local variables (compiler requires assignment)Automatic default values for all instance fields
public void createVehicle() {
    int wheelCount = 4;             // Primitive stored directly on the Stack
    Car familyCar = new Car();      // 'familyCar' reference on Stack; Car object on Heap
}

[!IMPORTANT] Pointers, Not Objects: A reference variable never contains the actual object data itself. A reference variable is merely a pointer—a value holding the memory address where the object resides on the heap. When you access an object property (such as familyCar.mileage), the JVM uses the address stored in familyCar to traverse into heap memory and read the mileage field.


5. Multiple Reference Variables Pointing to the Same Object (Aliasing)

In Java, assigning one reference variable to another does not copy the object. Instead, it copies the reference address stored inside the variable. This creates aliasing—multiple reference variables on the stack pointing to the exact same object on the heap:

Car carA = new Car();
carA.mileage = 150.0;

// Copy the reference address from carA into carB
Car carB = carA;

// Mutate the object via carB
carB.mileage = 300.0;

// Inspect the object via carA
System.out.println(carA.mileage); // Prints: 300.0!
System.out.println(carA == carB); // Prints: true (both hold identical heap addresses)

Because carA and carB hold the exact same memory address, any modification made through carB is immediately visible when inspecting carA. Furthermore, the equality operator (==) compares the primitive addresses held inside reference variables; because both variables point to the same heap address, carA == carB evaluates to true.


6. Object Lifecycle and Garbage Collection Eligibility

Java eliminates manual memory deallocation. Unlike languages where developers must pair every allocation with explicit deallocation commands, Java features an automated Garbage Collector (GC). The Garbage Collector is a background daemon thread managed by the JVM that automatically detects and reclaims heap memory occupied by objects that are no longer in use.

The Core Rule of GC Eligibility

An object on the heap becomes eligible for garbage collection at the precise moment it is no longer reachable by any live thread through any chain of valid reference pointers starting from a GC Root.

A GC Root is any reference that is intrinsically reachable, including:

  • Local reference variables currently active in any thread's call stack frame.
  • Static reference variables belonging to loaded classes in Metaspace.
  • Active Java Native Interface (JNI) references.

The Three Classic Dereferencing Scenarios

The 1Z0-811 exam frequently provides code snippets and asks candidates to identify the exact line where an object becomes eligible for GC. Objects lose reachability via three primary mechanisms:

1. Reference Explicitly Assigned to null

Car c = new Car(); // Car Object 1 allocated on Heap; c points to Object 1
c = null;          // c no longer points to Object 1. Object 1 is now eligible for GC!

2. Reference Variable Reassigned to Another Object

Car c1 = new Car(); // Car Object 1 allocated
Car c2 = new Car(); // Car Object 2 allocated

c1 = c2;            // c1 now points to Object 2!
                    // Car Object 1 has ZERO references pointing to it.
                    // Car Object 1 is now eligible for GC!

3. Reference Variable Goes Out of Scope

When a method or block finishes executing, its stack frame is popped from the JVM stack. All local reference variables declared within that block cease to exist:

public void executeTask() {
    Car tempCar = new Car(); // tempCar points to Object 1 on Heap
    tempCar.drive(10);
} // Method terminates! The stack frame pops, destroying 'tempCar'.
  // Object 1 has no remaining references and is eligible for GC immediately!

[!WARNING] The System.gc() Fallacy: Calling System.gc() or Runtime.getRuntime().gc() merely sends a polite suggestion or hint to the JVM that garbage collection may be beneficial. The JVM specification provides no guarantee that the garbage collector will execute immediately, execute at all, or collect any specific object upon invoking System.gc(). Never rely on System.gc() for predictable program behavior or exam answers!


7. Islands of Isolation: Circular References

A classic, high-yield exam topic involves islands of isolation. Consider two objects that contain fields referencing each other:

class Node {
    Node neighbor;
}

public class IslandDemo {
    public static void main(String[] args) {
        Node n1 = new Node(); // Object A created
        Node n2 = new Node(); // Object B created

        n1.neighbor = n2;     // Object A points to Object B
        n2.neighbor = n1;     // Object B points to Object A

        // Cut off external references from the Stack
        n1 = null;
        n2 = null;
        // POINT X: Are Object A and Object B eligible for GC?
    }
}

At Point X, Object A still holds a reference to Object B (via its neighbor field), and Object B still holds a reference to Object A. However, neither Object A nor Object B can be reached from any active GC root on the thread stack!

Because Java uses tracing garbage collection (reachability analysis) rather than naive reference counting, the Garbage Collector starts at active stack frames and static fields. Finding no path connecting any live thread to the mutually referencing group, the JVM recognizes that Object A and Object B constitute an isolated island. Both objects become eligible for garbage collection simultaneously at Point X.

Loading diagram...
Stack vs. Heap Memory: References, Aliasing, and Island of Isolation
Test Your Knowledge

Consider the following code snippet:

public class DeviceManager {
    public static void main(String[] args) {
        Device d1 = new Device("Laptop");
        Device d2 = new Device("Tablet");
        Device d3 = d1;
        d1 = null;
        d2 = d3;
        // Point X
    }
}
At Point X, how many Device objects created in main are eligible for garbage collection?

A
B
C
D
Test Your Knowledge

Consider the following class definition and test execution:

class Account {
    int balance;
}

public class BankTest {
    public static void main(String[] args) {
        Account a1 = new Account();
        a1.balance = 500;
        Account a2 = a1;
        a2.balance = 800;
        System.out.println(a1.balance + " " + (a1 == a2));
    }
}
What is the output of running this program?

A
B
C
D
Test Your Knowledge

Consider two objects, Node A and Node B. Node A has an instance field pointing to Node B, and Node B has an instance field pointing to Node A. All external stack reference variables pointing to Node A and Node B are subsequently assigned to null. Which statement correctly describes the Garbage Collection status of Node A and Node B?

A
B
C
D