In Java, understanding how data is passed to methods is a fundamental concept for every developer. To demystify this, we must distinguish between primitive types and object references.
Core Principles of Parameter Passing
When you pass a value to a method, Java behaves based on the data type:
- Primitive types (int, char, boolean, etc.): The method receives a copy of the actual value. Modifying this copy inside the method has no effect on the original variable.
- Object types (classes, arrays, strings): The method receives a copy of the reference (the memory address) to the object. If you modify the object's internal state (e.g., calling a setter), the change persists. However, if you reassign the parameter to a new object instance within the method, the orgiinal reference remains unchanged.
Code Illustration
Consider the following implementation, which contrasts variable modification with reference reassignment:
public class ParameterHandler {
public void modifyData(int value, StringBuilder builder) {
// Primitive: modification is local to this method
value += 50;
// Object: modifying internal state affects the original object
builder.append(" - Processed");
}
public void reassignReference(StringBuilder builder) {
// Reassignment: the reference copy now points elsewhere
// The original variable in the caller remains unchanged
builder = new StringBuilder("New Instance");
}
public static void main(String[] args) {
int myNum = 10;
StringBuilder myText = new StringBuilder("Initial");
ParameterHandler handler = new ParameterHandler();
handler.modifyData(myNum, myText);
System.out.println(myNum); // Output: 10
System.out.println(myText); // Output: Initial - Processed
}
}
Special Considerations: The String Type
A common source of confusion is the String class. Because Java strings are immutable, you cannot change the contents of an existing String object. Any method that appears to "modify" a string (like substring(), concat(), or toUpperCase()) actually creates a new String object and returns it.
Because the parameter is just a reference, reassignment inside a method will never reflect in the caller's scope unless the result is returned and reassigned by the caller:
// Correct pattern for String modification
public String updateString(String input) {
return input.concat("_Modified");
}
// In usage:
String data = "Hello";
data = updateString(data); // Must reassign result
If you need to pass mutable data that can be changed within a method, consider using mutable wrappers like StringBuilder or a custom object with specific fields, rather than passing raw String values.