Object Creation and Storage (Instantiation)
Learning Objectives
By the end of this lesson, you will be able to:
-
Understand how Java assigns memory for objects and primitives
-
Tell the difference between stack and heap memory
-
Explain the difference between pass-by-value and pass-by-reference
-
Create and instantiate objects using constructors
Brief Overview
| Concept | Easy Explanation | |——————-|—————————————————| | Memory for objects | Java puts tiny toys on your desk, big toy boxes in another room | | Stack | Your desk — for small things | | Heap | The playroom — for big things | | Pass-by-value | You share a copy of your toy | | Pass-by-reference | You share the same toy box | | Constructor | A machine that builds your toy boxes (objects) |
What is Instantiation?
Instantiation is the process of creating an actual instance (object) of a class. When you instantiate an object, you’re allocating memory and initializing it based on the class blueprint.
// Class Dog is the blueprint
class Dog {
String name;
int age;
}
// Instantiation creates objects from the blueprint
Dog myDog = new Dog(); // Creating an instance
Dog yourDog = new Dog(); // Creating another instance
Think of a class as a cookie cutter and objects as the actual cookies you make with it!

Memory Allocation: Stack and Heap
In Java, memory allocation for variables occurs in two main areas:
- the stack
- the heap
Stack and Heap are places where you can send your data to be used later!
Stack Memory
Stack memory operates on a Last-In-First-Out idea, like a stack of plates, you can only grab one from the top, not from the middle.
Charecteristics
- Stores primitive data types (int, double, boolean, char, etc.)
- Each thread has its own stack (thread-safe)
- Automatically managed - memory is freed when method returns
- Fast allocation and deallocation
- Limited in size (can cause StackOverflowError)
public class StackDemo {
public static void main(String[] args) {
int number = 100; // Primitive stored in stack
double price = 49.99; // Primitive stored in stack
boolean isActive = true; // Primitive stored in stack
String name; // Reference stored in stack (and in heap)
System.out.println("Number: " + number);
System.out.println("Price: " + price);
System.out.println("Is Active: " + isActive);
}
}
College Board tests these concepts!
-
Primitives point directly to their value - Since primitives are always on the stack they contain their actual value, not a reference.
-
Reference types contain an address - A reference variable (like for objects) contains the memory address where the actual object lives on the heap.
-
Method parameters create copies - Passing a variable to a method creates a copy of that variable’s content.
-
Pass-by-value for primitives - Changes to primitive parameters inside a method don’t affect the original variable.
-
Pass-by-reference for objects - Since references are copied, changes to object contents ARE reflected in the original object.
Heap Memory
Heap memory is like a playroom, filled with toys (data/primitives) everywhere that you can grab in any order

Characteristics:
- Used for storing objects and arrays
- Shared among all threads (requires synchronization)
- Larger than stack memory
- Slower allocation compared to stack
- Objects live here until no references point to them
public class HeapDemo {
public static void main(String[] args) {
// Explicit object creation
String message = new String("Hello"); // Object created on heap,
// message is referenced in the stack
// Arrays stored on heap
int[] numbers = new int[5]; // Array object on heap
// numbers reference is on stack
// Custom objects
Dog myDog = new Dog(); // Dog object on heap
// myDog reference is on stack
System.out.println("Message: " + message);
System.out.println("Numbers array length: " + numbers.length);
}
}
Heap Variables –> Tips
-
Heap variables stay alive as long as at least one stack variable points to them.
-
All reference data types refer to an address on the stack but change content on the heap.
-
Objects created in the heap are globally accessible and can be shared among multiple methods
Popcorn Hack #1: Stack vs Heap
Run the following code in your own notebook and observe:
public class MemoryDemo {
public static void main(String[] args) {
// Stack variables
int a = 10;
int b = a; // Copy of value
b = 20; // Changing b doesn't affect a
System.out.println("Primitives (Stack):");
System.out.println("a = " + a); // Still 10
System.out.println("b = " + b); // Now it's 20
// Heap variables
int[] array1 = {1, 2, 3};
int[] array2 = array1; // Copy of reference (address)
array2[0] = 99; // Changing array2 DOES affect array1
System.out.println("\nArrays (Heap):");
System.out.println("array1[0] = " + array1[0]); // Now it's 99!
System.out.println("array2[0] = " + array2[0]); // Also 99
}
}
Tasks:
Answer in a few sentences in your notebook
-
Why does changing b not affect a, but changing array2 affects array1?
-
Describe what’s on the stack vs. the heap for this code.
Pass-by-Value vs Pass-by-Reference
This is critical for College Board CSA AP Exam!
Key Concepts:
Pass-by-Value (Primitives):
When you pass a primitive to a method, Java copies the value Changes inside the method do NOT affect the original variable
Pass-by-Reference (Objects):
When you pass an object to a method, Java copies the reference (address) Changes to the object’s contents ARE reflected in the original object However, reassigning the reference itself doesn’t affect the original reference
Example: pass-by-value
Pass-by-Value (Copy of the toy)
Imagine you have a toy car. You give a copy of it to your friend. If your friend paints the copy red, your original toy doesn’t change.
public class IntByValue {
// Method tries to change the number
public static void changeInt(int n) {
n = n + 10; // only changes the copy
System.out.println("Inside method: n = " + n);
}
public static void main(String[] args) {
int n = 5; // original number
System.out.println("Before method: n = " + n);
changeInt(n); // pass copy of n
System.out.println("After method: n = " + n); // still 5
}
}
// Run main manually
IntByValue.main(null);
Main method before changeInt(n): n = 5
In changeInt method
Before n += 10: n = 5
After n += 10: n = 15
Main method after changeInt(n): n = 5
Example: pass-by-refrence
Pass-by-Reference (Shared toy box)
Now imagine a toy box with many toys inside. You give your friend the address of your toy box, not a copy. If your friend paints a toy inside the box, your toys also change, because it’s the same box.
// A simple class to hold a number
class NumberHolder {
int value;
NumberHolder(int value) {
this.value = value;
}
}
public class PassByReferenceDemo {
// Method that changes the object's value
public static void changeValue(NumberHolder n) {
n.value = n.value + 10; // modify the object
}
public static void main(String[] args) {
NumberHolder myNumber = new NumberHolder(5); // create object
System.out.println("Before: " + myNumber.value); // 5
changeValue(myNumber); // pass object reference
System.out.println("After: " + myNumber.value); // 15
}
}
Before: 21 16
After: 16 21
Before: 16 21
After: 16 21
Before: 16 -1
After: -1 16
Popcorn Hack #2: Understanding Pass-by-Reference
Examine the code below and predict the output before running it:
public class PersonDemo {
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public static void haveBirthday(Person p) {
p.age = p.age + 1; // Modifying object content
System.out.println("Inside method: " + p.name + " is now " + p.age);
}
public static void reassignPerson(Person p) {
p = new Person("New Person", 99); // Reassigning reference
System.out.println("Inside reassign: " + p.name + " is " + p.age);
}
public static void main(String[] args) {
Person john = new Person("John", 20);
System.out.println("Before birthday: " + john.name + " is " + john.age);
haveBirthday(john);
System.out.println("After birthday: " + john.name + " is " + john.age);
System.out.println("\nBefore reassign: " + john.name + " is " + john.age);
reassignPerson(john);
System.out.println("After reassign: " + john.name + " is " + john.age);
}
}
Questions:
-
After haveBirthday(john) is called, what is John’s age? Why?
-
After reassignPerson(john) is called, what is John’s name and age? Why?
-
Explain the difference between modifying an object’s contents vs. reassigning a reference.
Constructors and Object Creation
Constructors are special methods that initialize objects when they’re created. Understanding constructors is essential for proper object instantiation.
// Basics:
public class Student {
private String name;
private int grade;
private double gpa;
// Default constructor
public Student() {
this.name = "Nora";
this.grade = 111;
this.gpa = 5.0;
}
// Parameterized constructor
public Student(String name, int grade, double gpa) {
this.name = name;
this.grade = grade;
this.gpa = gpa;
}
public void display() {
System.out.println("Name: " + name + ", Grade: " + grade + ", GPA: " + gpa);
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("Soni", 11, 1.0);
s1.display();
s2.display();
}
}
Student.main(null);
Name: Nora, Grade: 111, GPA: 5.0
Name: Soni, Grade: 11, GPA: 1.0
Constructor Types:
- Default Constructor: No parameters, sets default values
- Parameterized Constructor: Takes parameters to initialize with specific values
- Copy Constructor: Creates a new object as a copy of an existing object
Key Takeaways
-
Stack stores primitives and object references; Heap stores actual objects
-
Primitives are pass-by-value; Objects are pass-by-reference (reference is copied)
-
Understanding memory allocation helps debug issues and write efficient code
-
Constructors initialize objects when they’re created
-
These concepts are frequently tested on the College Board AP CS A exam!