Skip to content
Java oop basics 6 min read

Object vs Class

A class is the blueprint; an object is the thing built from that blueprint. You write a class once and create as many objects from it as you need — each object gets its own copy of the data but shares the same set of instructions.

The Blueprint vs the Instance

Think of a class like an architectural drawing of a house. The drawing describes the number of rooms, windows, and doors, but it is not a house you can live in. When a construction crew builds a house using those plans, that house is the object — a real, physical thing that takes up space and has a specific address.

ConceptClassObject
What it isA template / blueprintA concrete instance
Exists inSource code (.java file)JVM memory (heap) at runtime
When createdAt compile time (as .class bytecode)At runtime with new
MemoryNo heap memory allocatedAllocated on the heap
CountDefined onceCan have many from one class
ExampleDog (the idea of a dog)myDog (your actual dog)

Defining a Class

A class declaration names the type, then lists its fields (data) and methods (behavior) inside curly braces.

public class Dog {
    // Fields — each object gets its own copy of these
    String name;
    String breed;
    int age;

    // Method — behaviour shared by all Dog objects
    void bark() {
        System.out.println(name + " says: Woof!");
    }
}

At this point, Dog is just bytecode sitting in memory. No dog actually exists yet.

Creating an Object

You create an object with the new keyword, which allocates memory on the heap and calls the constructor.

public class Main {
    public static void main(String[] args) {
        // Create two separate Dog objects from the same blueprint
        Dog dog1 = new Dog();
        dog1.name  = "Rex";
        dog1.breed = "German Shepherd";
        dog1.age   = 3;

        Dog dog2 = new Dog();
        dog2.name  = "Bella";
        dog2.breed = "Labrador";
        dog2.age   = 5;

        dog1.bark();
        dog2.bark();
    }
}

Output:

Rex says: Woof!
Bella says: Woof!

dog1 and dog2 are independent objects. Changing dog1.age has zero effect on dog2.age — they live in separate memory locations on the heap.

Tip: You can create as many objects as you need from a single class. Each one is completely independent unless you deliberately share state through static fields (see static Keyword).

Reference Variables vs Objects

A variable like Dog dog1 is a reference variable — it holds the memory address of the object, not the object itself. This distinction matters when you assign one variable to another.

Dog a = new Dog();
a.name = "Max";

Dog b = a;          // b points to the SAME object as a
b.name = "Charlie";

System.out.println(a.name); // Charlie — same object!

Output:

Charlie

Here there is still only one Dog object on the heap. Both a and b are references that point to it. Modifying the object through b is visible through a because they share the same address.

Warning: Confusing reference copying (b = a) with object copying is a common bug. If you need a true independent copy, implement clone() or write a copy constructor. Learn more on the Object Cloning page.

null — A Reference That Points Nowhere

A reference variable that has not been assigned an object holds null.

Dog stray = null;
System.out.println(stray); // null

// Calling a method on null throws NullPointerException
stray.bark(); // ❌ NullPointerException at runtime

Always initialise a reference before using it, or guard with a null check.

The new Keyword Step by Step

When you write new Dog(), three things happen in order:

  1. Memory allocation — the JVM reserves space on the heap for all of Dog’s instance fields.
  2. Initialisation — field default values are applied (0 for numeric types, null for references, false for booleans).
  3. Constructor call — the constructor runs and the object is ready for use.

The new expression evaluates to the memory address of the freshly created object, which is stored in your reference variable. See Constructors for how to customise step 3.

Class Members vs Instance Members

A class can contain two kinds of members:

  • Instance members — fields and methods that belong to each individual object.
  • Static members — fields and methods that belong to the class itself, shared by every object.
public class Counter {
    int count;              // instance field — each Counter has its own
    static int total = 0;  // static field — shared by ALL Counter objects

    Counter() {
        total++;            // every new Counter increments the shared counter
    }
}

public class Main {
    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = new Counter();
        Counter c3 = new Counter();

        System.out.println("Total counters: " + Counter.total);
    }
}

Output:

Total counters: 3

Note: Access static members via the class name (Counter.total), not through an object reference — it makes the intent clear and avoids misleading code.

Under the Hood

Memory Layout

When new Dog() runs, the JVM allocates a contiguous block of memory on the heap large enough to hold:

  • A mark word (object header — stores identity hash code, GC flags, lock state).
  • A class pointer (klass pointer) — a reference back to the Dog class’s internal metadata in the metaspace.
  • The actual instance field values in declaration order, aligned to word boundaries.

The reference variable on the stack (or inside another heap object) stores the compressed 4-byte or raw 8-byte address of that heap block.

The Class Object at Runtime

The .class file compiled from your source becomes a java.lang.Class object loaded into metaspace (formerly PermGen, replaced in Java 8). Every instance’s class pointer leads back to that single Class object. This is why dog1.getClass() == dog2.getClass() is always true — both objects share the same class metadata. You can inspect it at runtime using the Reflection API.

Garbage Collection

Because objects live on the heap, the Garbage Collector is responsible for reclaiming them. An object becomes eligible for collection once no live reference points to it.

Dog temp = new Dog(); // object created
temp = null;          // no references remain → eligible for GC

The class itself (its Class object in metaspace) stays loaded as long as its ClassLoader is reachable. For most application classes that means the entire JVM lifetime.

Quick Cheat Sheet

// 1. Define the class (blueprint)
class Person {
    String name;
    int age;
    void greet() { System.out.println("Hi, I'm " + name); }
}

// 2. Create objects (instances)
Person alice = new Person();
alice.name = "Alice";
alice.age  = 30;

Person bob = new Person();
bob.name = "Bob";
bob.age  = 25;

// 3. Use them
alice.greet(); // Hi, I'm Alice
bob.greet();   // Hi, I'm Bob

// 4. Both share the same class
System.out.println(alice.getClass() == bob.getClass()); // true

Understanding this blueprint-vs-instance distinction is the foundation of everything else in OOP — from inheritance to polymorphism. Get comfortable with it before moving on.

Last updated June 13, 2026
Was this helpful?