ExerciseChallenge
Challenge
Mutate or reassign
20 minjunior0–6 yrs
Edge cases. You have to reason, and two valid fixes differ.
What this teaches
- Following the reference is visible to the caller; moving it is not
- The same parameter type gives opposite outcomes depending on one line
- Setting a parameter to null does nothing at all
- Immutable arguments remove the ambiguity entirely
Starter
Starter.java
import java.util.*;
/**
* Challenge: six methods, one parameter type, opposite outcomes.
*
* Predict every line of output before you run this. Write your predictions
* down — being wrong on paper once is the point.
*
* For each method, ask exactly one question: does the body FOLLOW the arrow, or
* MOVE the arrow?
*/
public class Starter {
static void a(List<String> list) {
list.add("a");
}
static void b(List<String> list) {
list = new ArrayList<>();
list.add("b");
}
static void c(List<String> list) {
list.add("c1");
list = new ArrayList<>();
list.add("c2");
}
static void d(List<String> list) {
list = null;
}
static void e(List<String> list) {
list.clear();
}
static void f(StringBuilder sb) {
sb.append("!");
sb = new StringBuilder("ignored");
sb.append("?");
}
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
a(l1);
System.out.println("a -> " + l1);
List<String> l2 = new ArrayList<>();
b(l2);
System.out.println("b -> " + l2);
List<String> l3 = new ArrayList<>();
c(l3);
System.out.println("c -> " + l3);
List<String> l4 = new ArrayList<>(List.of("survivor"));
d(l4);
System.out.println("d -> " + l4 + " size=" + l4.size());
List<String> l5 = new ArrayList<>(List.of("x", "y"));
e(l5);
System.out.println("e -> " + l5);
StringBuilder sb = new StringBuilder("start");
f(sb);
System.out.println("f -> " + sb);
// TODO 1: for each of a-f, write a one-word note: "follows" or "moves".
// Method c and f each do both — say which statement did what.
// TODO 2: state the rule in one sentence, WITHOUT using the word
// "reference" more than once. If you cannot, you do not have it yet.
// TODO 3: write a method that takes a list and genuinely cannot modify
// the caller's list — enforced by the code, not by a comment.
//
// static int countLongNames(??? names)
//
// Then explain what happens if a caller passes a mutable list to it
// anyway, and whether the ELEMENTS are protected too.
}
}Run it locally:
cd exercises/java/oop/pass-by-value/02-challenge
javac Starter.java -d /tmp/out && java -cp /tmp/out StarterHints
Hint 1
For each method ask one question: does this line follow the arrow, or move the arrow? Only the first is visible outside.
Hint 2
sb.append(...) follows it. sb = ... moves it. There is no third case.
Hint 3
null is just another value to assign to the parameter.
Hint 4
For the last task, think about what the caller can still do to the object after handing it over — and how to take that ability away.
Done when
- You predicted all six outputs before running, and can explain each
- You can state the rule in one sentence without using the word reference twice
- The final method cannot modify the caller's list, enforced by the types