Study guide

6.2 Argument Passing: Pass-by-Value Mechanics

Oracle Certified Foundations Associate, Java 1Z0-811

Track your progress as you read

Finished sections get a check mark.

1 Introduction & Exam Overview

1Z0-811 Exam Overview & Certification Path Setting Up the JDK 8 Environment & Recommended Study Plan

2 Chapter 1: Java Basics & Program Architecture

1.1 What Is Java & Core Platform Features 1.2 The Java Runtime Architecture & Memory Management 1.3 Structure of a Java Program & The main Method 1.4 Compiling, Running, and Package Management

3 Chapter 2: Working with Data Types & Strings

2.1 The Eight Primitive Data Types & Literal Values 2.2 Type Conversion, Casting, and Numeric Promotion 2.3 The String Class, Immutability, and the String Constant Pool 2.4 String Methods, StringBuilder Operations, and Type Parsing

4 Chapter 3: Operators & Decision Statements

3.1 Arithmetic, Relational, and Logical Operators 3.2 Unary Operators, Assignment, and Operator Precedence 3.3 Decision Making: if, if-else, and the Ternary Operator 3.4 The switch Statement & Multi-Way Branching

5 Chapter 4: Working with Java Arrays and ArrayLists

4.1 Array Declaration, Instantiation, and Initialization 4.2 Array Indexing, Bounds Checking, and Iteration Mechanics 4.3 Two-Dimensional and Ragged Arrays 4.4 ArrayList Fundamentals, Operations, and Array Comparison

6 Chapter 5: Using Looping Statements

5.1 While and Do-While Loops 5.2 Standard for Loops & Control Flow 5.3 The Enhanced For-Each Loop 5.4 Branching with Break and Continue

7 Chapter 6: Working with Methods

6.1 Method Declaration, Parameters, and Return Types 6.2 Argument Passing: Pass-by-Value Mechanics 6.3 Method Overloading Principles 6.4 Static vs. Instance Methods and Variable Scoping Rules

8 Chapter 7: Classes, Objects, and Constructors

7.1 Defining Classes and Instantiating Objects 7.2 Constructor Rules and Overloading 7.3 The this Reference and Constructor Chaining

9 Chapter 8: Encapsulation, Inheritance, and Members

8.1 Encapsulation and Access Modifiers 8.2 Inheritance Fundamentals and the super Keyword 8.3 Method Overriding and Polymorphic Method Execution

10 Chapter 9: Debugging, Documentation, and Exceptions

9.1 Syntax Errors, Runtime Errors, and Logic Errors 9.2 Documentation with Javadoc & Core Utilities 9.3 Exception Hierarchy & Defensive try-catch 9.4 The finally Block & Common Runtime Exceptions

6.2 Argument Passing: Pass-by-Value Mechanics

Key Takeaways Explain This Topic AI

Java strictly and unconditionally evaluates all method arguments using pass-by-value; there is no pass-by-reference mechanism anywhere in the Java language.

When passing primitive data types, a duplicate copy of the literal bit pattern is passed; modifying the parameter inside the callee method has zero effect on the caller's variable.

When passing object reference variables, a copy of the memory address (reference) is passed by value; both caller and callee point to the exact same object instance on the heap.

Invoking mutating methods or modifying fields on a passed object reference alters the shared heap object, whereas reassigning the parameter variable itself affects only the callee's local stack frame.

Instances of String and primitive wrapper classes are strictly immutable; methods operating on them cannot alter their heap state, and parameter reassignment has zero effect on the caller.

Last updated: September 2026

6.2 Argument Passing: Pass-by-Value Mechanics

Note

Exam Focus : Pass-by-value semantics is one of the most heavily tested and commonly misunderstood concepts on the Oracle Certified Foundations Associate, Java (1Z0-811) examination. Certification questions routinely present intricate code snippets involving primitive variables, mutable objects ( StringBuilder , arrays, custom classes), and immutable objects ( String , wrapper classes) passed into methods to determine whether candidates can accurately track variable state across method boundaries.

A foundational architectural principle of the Java Virtual Machine is its evaluation model for method arguments: Java is strictly and unconditionally pass-by-value . There is no pass-by-reference in Java . Regardless of whether an argument is a primitive 32-bit int or an object reference like ArrayList<String> , Java always passes a copy of the value stored inside the variable.

However, widespread confusion arises because the "value" of an object variable is the memory reference (address) pointing to the object on the Java Heap. Mastering how this evaluation model operates across Stack frames and Heap storage is the key to solving every parameter-passing question on the examination.

JVM Memory Architecture: Stack vs. Heap

To understand parameter passing, one must understand how the JVM partitions runtime data:

The JVM Call Stack : Each executing thread maintains its own call stack. Whenever a method is invoked, a new stack frame is pushed onto the stack. The stack frame stores the method's local variables, formal parameter variables, and intermediate calculation operands. When the method completes, its stack frame is popped off and discarded, instantly destroying all local variables contained within it.

The Java Heap : The heap is the global, shared memory region where all objects and array instances reside. Objects are dynamically allocated on the heap using the new operator and persist until they become unreachable and are reclaimed by the Garbage Collector. Stack Frame (Caller) Stack Frame (Callee) Java Heap Memory

  • ┌──────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐
  • │ int a = 50 │ │ int x = 50 (copy)│ │ (Heap Objects Shared) │
  • │ Ref b = 0x10A4 │─────────┼─> Ref p = 0x10A4 ┼─────────>│ Object @ 0x10A4 │
  • └──────────────────┘ └──────────────────┘ └─────────────────────────┘
  • Passing Primitive Data Types by Value

When a primitive variable ( byte , short , int , long , float , double , char , boolean ) is passed as an argument, a copy of its literal bit pattern is created and assigned to the method's formal parameter.

Execution Lifecycle of Primitive Passing

The caller variable holds a concrete primitive value in its stack frame.

Upon invocation, a new stack frame is pushed for the callee, and the parameter variable is initialized with a copy of the primitive value.

Any arithmetic operation, modification, or reassignment applied to the parameter inside the callee operates exclusively within the callee's stack frame.

When the callee returns, its stack frame is destroyed. The caller's variable in the caller frame remains entirely unchanged. public class PrimitivePassingDemo {

  • public static void modifyPrimitive(int value) {
  • value = value + 100; // Modifies only the local parameter 'value'
  • System.out.println("Inside modifyPrimitive: " + value); // Prints 150
  • }
  • public static void main(String[] args) {
  • int original = 50;
  • System.out.println("Before call: " + original); // Prints 50
  • modifyPrimitive(original); // Passes a bit-level copy of 50

System.out.println("After call: " + original); // Still prints 50!

  • }
  • }

Even though the parameter variable value was modified to 150 inside modifyPrimitive() , the caller's variable original retains its initial value 50 . There is no mechanism in Java for a callee to modify the caller's primitive variable.

Passing Object Reference Variables by Value

In Java, variables declared with a class, interface, or array type do not store the object itself. Instead, they hold a reference (a memory pointer address) that indicates where the object resides on the heap.

When an object reference variable is passed to a method, Java still applies pass-by-value : the reference address itself is copied by value .

What Occurs in Memory During Object Passing

The caller holds a reference variable containing an address (e.g., 0x4A20 ) pointing to a heap object.

When invoking a method, the address 0x4A20 is copied into the callee's parameter variable in the callee's new stack frame.

Both the caller's variable and the callee's parameter now contain copies of the same address. Both point to the exact same underlying object on the heap!

This leads to two fundamentally different outcomes depending on what actions the callee takes:

Mutating the Object's State : Modifying the object's instance fields or invoking state-altering methods modifies the single shared object on the heap. The caller will see these changes.

Reassigning the Parameter Variable : Assigning a new object or null to the parameter variable modifies only the callee's local reference pointer. The caller's reference variable is completely unaffected .

Mutating Object State vs. Reassigning Reference Parameters

Distinguishing between state mutation and reference reassignment is the single most critical parameter-passing skill evaluated on the 1Z0-811 examination.

  • Scenario 1: Mutating Object State (Affects Caller) class Account {
  • int balance;
  • Account(int b) { this.balance = b; }
  • }
  • public class MutationDemo {
  • public static void creditBonus(Account acc) {

acc.balance += 250; // Mutates the state of the shared object on the Heap!

}

  • public static void main(String[] args) {
  • Account primary = new Account(1000);
  • creditBonus(primary);
  • System.out.println("Primary balance: " + primary.balance); // Prints 1250
  • }
  • }

Analysis : In this scenario, both primary (in main ) and acc (in creditBonus ) hold the exact same heap memory address. Executing acc.balance += 250 modifies the balance field of that heap object. When creditBonus() returns, primary.balance reflects the updated balance 1250 .

  • Scenario 2: Reassigning the Parameter Variable (Zero Effect on Caller) public class ReassignmentDemo {
  • public static void resetAccount(Account acc) {
  • // TRAP: Instantiating a new object and reassigning the local parameter
  • acc = new Account(0);

acc.balance = 500; // Mutates ONLY the new object @ 0x9B11!

}

  • public static void main(String[] args) {
  • Account primary = new Account(1000); // Resides @ 0x4A20
  • resetAccount(primary);

System.out.println("Primary balance: " + primary.balance); // Still prints 1000!

  • }
  • }

Analysis : Inside resetAccount() , the expression acc = new Account(0) creates a second, distinct Account object at address 0x9B11 on the heap and updates the local parameter acc to hold 0x9B11 . The caller's variable primary in main() continues holding 0x4A20 . Modifying acc.balance or setting acc = null has zero impact on primary .

The Classic "Swap" Method Fallacy

In programming languages supporting true pass-by-reference (such as C++ with & references), a function can swap two caller variables. In Java, writing a method to swap two variables is completely impossible : public class SwapFallacy {

  • public static void swap(Integer first, Integer second) {
  • Integer temp = first;
  • first = second;
  • second = temp;

// Only local parameter variables in swap()'s stack frame were swapped!

}

  • public static void main(String[] args) {
  • Integer num1 = 10;
  • Integer num2 = 20;
  • swap(num1, num2);
  • System.out.println("num1=" + num1 + ", num2=" + num2); // Prints: num1=10, num2=20
  • }
  • }

Because swap() merely exchanges the pointer addresses stored in its local stack parameter slots first and second , the caller variables num1 and num2 in main() remain entirely unchanged.

The Immutable Objects Trap: String and Wrapper Classes

A favorite exam scenario involves passing instances of String or primitive wrapper classes ( Integer , Double , Boolean , etc.) into a method. Novice programmers often mistakenly expect them to behave like mutable objects because they are reference types.

However, String and all standard primitive wrapper classes are strictly immutable . Once instantiated on the heap, their internal state can never be modified! public class StringTrapDemo {

public static void updateString(String text) {

text.concat(" World"); // Creates a new String "Hello World", but return value is discarded!

  • text = text + "!"; // Creates a new String "Hello!" and reassigns local parameter 'text'
  • }
  • public static void main(String[] args) {
  • String greeting = "Hello";
  • updateString(greeting);
  • System.out.println(greeting); // Prints "Hello", NOT "Hello World" or "Hello!"
  • }
  • }
  • In contrast, StringBuilder is a mutable character sequence: public class StringBuilderDemo {
  • public static void updateBuilder(StringBuilder sb) {

sb.append(" World"); // Mutates the internal buffer of the shared heap object directly!

}

  • public static void main(String[] args) {
  • StringBuilder greeting = new StringBuilder("Hello");
  • updateBuilder(greeting);

System.out.println(greeting); // Prints "Hello World"!

  • }
  • }
  • Passing Arrays to Methods

In Java, arrays are first-class objects . Consequently, passing an array to a method follows the exact same object reference mechanics: public class ArrayPassingDemo {

  • public static void modifyArray(int[] numbers) {
  • numbers[0] = 999; // Mutates shared heap array element (Affects caller!)
  • numbers = new int[]{ 1, 2 }; // Reassigns local parameter pointer (Zero caller effect!)
  • }
  • public static void main(String[] args) {
  • int[] values = { 10, 20, 30 };
  • modifyArray(values);

System.out.println(values[0]); // Prints 999!

System.out.println(values.length); // Still prints 3!

  • }
  • }
  • Summary Comparison Table: Evaluation Models

Technical Dimension Primitive Types ( int , double , etc.) Mutable Reference Types ( StringBuilder , custom objects, arrays) Immutable Reference Types ( String , Integer , etc.)

  • What value is passed? Copy of literal primitive bits Copy of heap memory address Copy of heap memory address
  • Storage location Stack frame only Reference on Stack; Object on Heap Reference on Stack; Object on Heap

Effect of field / element mutation Not applicable (no fields) Mutates shared heap object ; caller observes change Not applicable (all fields are immutable/private)

Effect of calling transforming method Not applicable Mutates object (e.g., append() ) Returns new object ; original object unchanged

Effect of reassigning parameter ( p = ... ) Modifies local stack slot only; zero caller effect Modifies local stack slot only; zero caller effect Modifies local stack slot only; zero caller effect

Effect of setting parameter to null Compile error (cannot assign null to primitive) Clears local stack slot only; zero caller effect Clears local stack slot only; zero caller effect

Loading diagram... Stack vs. Heap Memory During Object Parameter Passing and Reassignment