Pass by Value
Learning Objectives Covered
By the end of this leasson, you will be able to predict whether changes a method makes to its arguments will be visible to the caller.
Learning Materials
Time Commitment
Approximately 40-45 minutes
Read (Approximately 10-15 minutes)
JavaRanch has a good explanation. You don’t need to read their “Cup Size story.” You just need to realize that variables are like cups at Starbucks: they have names and sizes.
Watch (Approximately 15 minutes)
The “Is Java pass by reference or pass by value?” example video on YouTube does a good job of explaining, too. And it gives example code!
Try (Approximately 20 minutes)
Instructions: Carefully read and consider each question, then choose an answer by clicking it.
NOTE: Once you click on an answer choice, you will be presented with an explanation for that choice. Some questions may have more than one correct answer.
Question 1
Given this next() method:
public void next(int previous, int current) {
int diff = current - previous;
previous = current;
current = current + diff;
}
Consider the following code:
int previous = 10;
int current = 13;
next(previous, current);
System.out.println(
String.format("Finished %d, ready for %d", previous, current) );
What will be printed?
Choice A
Finished 10, ready for 16
Reassigning the reference to previous
won’t work, but updating the value of current
will.
Finished 10, ready for 16
Reassigning the reference to previous
won’t work, but updating the value of current
will.
INCORRECT
The previous
and current
parameters are both primitive variables scoped to the next()
method, so changes in the method will have no effect on the variables outside the method.
Choice B
Finished 13, ready for 16
Java passes the value of the reference to the int
objects for prev
and current
, so their contents are updated in the next()
method.
Finished 13, ready for 16
Java passes the value of the reference to the int
objects for prev
and current
, so their contents are updated in the next()
method.
INCORRECT
Since int
is primitive, Java directly uses its value instead of creating a reference to it. The previous
and current
parameters to the next()
method are different primitives than the main previous
and current
variables, and therefore hold completely unrelated values.
Choice C
Finished 10, ready for 13
Changes to primitives in a method don’t affect variables outside the method.
Finished 10, ready for 13
Changes to primitives in a method don’t affect variables outside the method.
CORRECT!
Because the previous
and current
parameters of the next()
method are primitive variables limited to the scope of the method, they are completely unrelated to any variables outside the method.
Question 2
Given the applyCoupons()
method below:
public void applyCoupons(double[] prices) {
for (int i = 0; i < prices.length; i++) {
// 10% savings!
prices[i] -= prices[i] * 0.1D;
}
}
Consider the following code:
double[] costs = new double[2];
costs[0] = 10.0D;
costs[1] = 20.0D;
applyCoupons(costs);
System.out.println(
String.format("Reduced prices: [%f, %f]", costs[0], costs[1]));
Will this print the following? Why?
Reduced prices: [10.0, 20.0]
Choice A Yes, because the prices
parameter of applyCoupons()
has a different name from the outside variable costs
, so it doesn’t shadow costs
. Therefore changes to prices
will not be reflected in costs
.
INCORRECT
While prices
does not shadow costs
, they are not primitive values, so prices
receives the value of the reference to costs. They both refer to the same array.
Choice B No, because prices
and costs
refer to the same object, so changes made to one are reflected in the other.
CORRECT
An array of double
s is not a primitive, so Java copies the value of its reference into the applyCoupons()
parameter. Since prices
now refers to the same array as costs
, changes made in the method affect both variables.
Choice C Yes, because double
is primitive, so changes made in the applyCoupons()
method don’t affect variables outside the method.
INCORRECT
While double
is primitive, double[]
is not. Therefore the prices
parameter refers to the same array as costs
.
Question 3
Assume that:
- A
School
has afindStudent()
method that returns aStudent
when provided that student’s unique name. - A
GradeLevel
enumeration has anext()
method that returns the next expected grade (for instance,SEVENTH.next()
returnsEIGHTH
). - A
Student
includes a public field representing theirGradeLevel
.
Given the following graduate()
method that advances a student’s grade level only if they passed the course:
public void graduate(Student student, boolean passed) {
if (passed) {
student.gradeLevel = student.gradeLevel.next();
}
}
Consider this code:
Student student = School.findStudent("Goofus");
student.gradeLevel = GradeLevel.SEVENTH;
graduate(student, false);
student = School.findStudent("Gallant");
student.gradeLevel = GradeLevel.SEVENTH;
graduate(student, true);
Does either Goofus or Gallant advance to the eighth grade?
Choice A Yes, both Goofus and Gallant advance, because every student
refers to the same object.
INCORRECT
When we call student = School.findStudent('Gallant');
its existing reference to Goofus’s Student
is removed, and it is assigned a reference to Gallant’s Student
instead.
Choice B Yes, only Goofus advances. When graduate()
is called the first time, the graduate()
method’s parameter student
is assigned to reference Goofus, so when it’s called the second time, Goofus is advanced.
INCORRECT
At the end of the first call, the student
variable that was referencing Goofus goes out of scope and disappears. The second time, it’s assigned to reference Gallant.
Choice C Yes, only Gallant advances. When graduate()
is called the second time, it advances Gallant.
CORRECT
When graduate()
is called the second time, the parameter student
is assigned to the reference to Gallant. Therefore any changes made to the object are reflected outside the method.
Choice D No, neither Goofus nor Gallant advance. Because Java uses pass-by-value, the student information is copied into the student
parameter. Since it’s a copy, changing it doesn’t change the outside variables.
INCORRECT
While Java is pass-by-value, it doesn’t copy an entire object’s data. Instead, it copies a reference to object. Therefore, when graduate()
changes student.gradeLevel
, the object it references is changed.
Question 4
Given the following applyDiscount() method:
public double applyDiscount(double price, double discount) {
price -= price * discount;
return price;
}
Consider the following code:
double[] costs = new double[2];
costs[0] = 10.0D;
costs[1] = 20.0D;
costs[0] = applyDiscount(costs[0], 0.5D);
System.out.println(
String.format("Altered prices: [%f, %f]", costs[0], costs[1]));
Why does this print the following?
Altered prices: [5.0, 20.0]
Choice A Mu! It doesn’t! Because double is primitive, changes made in the applyDiscount()
method don’t affect variables outside the method.
INCORRECT
While changes in applyDiscount()
don’t affect variables outside, the calling code uses its return value to update costs[0]
.
Choice B Because the price
parameter of applyDiscount()
refers to the same object as costs[0]
, so changes to one are reflected in the other.
INCORRECT
Since price
and costs[0]
are both primitive double
s, Java directly uses their values. Therefore they are entirely separate variables, and do not affect each other
Choice C Because even though updating price
does not change costs[0]
, the reduced price
is returned and assigned to costs[0]
directly.
CORRECT
Since it returns the calculated value, the code can assign that to any variable it likes; and it does assign it to costs[0]
.