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.
| Concept | Class | Object |
|---|---|---|
| What it is | A template / blueprint | A concrete instance |
| Exists in | Source code (.java file) | JVM memory (heap) at runtime |
| When created | At compile time (as .class bytecode) | At runtime with new |
| Memory | No heap memory allocated | Allocated on the heap |
| Count | Defined once | Can have many from one class |
| Example | Dog (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
staticfields (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, implementclone()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:
- Memory allocation — the JVM reserves space on the heap for all of
Dog’s instance fields. - Initialisation — field default values are applied (
0for numeric types,nullfor references,falsefor booleans). - 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
Dogclass’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.
Related Topics
- Classes & Objects — detailed guide to defining fields, methods, and creating objects
- Constructors — how objects are initialised when
newis called - static Keyword — class-level members shared across all instances
- Object Cloning — making a true independent copy of an object
- Garbage Collection — how the JVM reclaims heap memory from unreachable objects
- Reflection API — inspecting and manipulating
Classobjects at runtime