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
}
}
MemoryDemo.main(new String[]{})
Primitives (Stack):
a = 10
b = 20
Arrays (Heap):
array1[0] = 99
array2[0] = 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.
Changing b doesn’t affect a because both b and a are smaller data types (integers) and are therefore primitives. This means that they store their actual values instead of an address saved on the heap that stores their values. Because of this, it changes its actual value rather than the data saved an address referenced by both variables. array2 and array1 both reference the same address stored on the heap and therefore a change will affect both because it changes the value stored in the address.
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
}
}
PassByReferenceDemo.main(new String[]{});
Before: 5
After: 15
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);
}
}
PersonDemo.main(new String[]{})
Before birthday: John is 20
Inside method: John is now 21
After birthday: John is 21
Before reassign: John is 21
Inside reassign: New Person is 99
After reassign: John is 21
The birthday won’t show the proper before and after while the name will.
Questions:
- After haveBirthday(john) is called, what is John’s age? Why?
- John’s age is now 21 because the command references a variable that is stored on the heap and changes the value that is stored in the address.
- After reassignPerson(john) is called, what is John’s name and age? Why?
- reassignPerson only changes the value directly of the new person and so the name and age of John don’t change from John and 21, respectively.
- Explain the difference between modifying an object’s contents vs. reassigning a reference.
- Modifying an object’s contents will change that object’s content as well as other things that reference that same address while reassigning an address will change the specific object only.
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!