9
$\begingroup$

I am an undergrad student. I am an experienced programmer. For reasons out of the scope of this question, I ended up in a class where basic things about C++ and Java are being taught (but I already know those).

I know very well the difference between "pass-by-value" and "pass-by-reference". I know very well that Java is "pass-by-value".

My teacher was talking about pointers and a bit later he showed an example of pass-by-reference in C++, comparing passing "by pointer", by value and by reference. So far so good.

But then he said "on the other hand, Java has a rule, primitive types are always passed by value, and non-primitive types are automatically passed by reference".

My question: I know that technically what he said is wrong. But I didn't say anything. No one else said anything, the other students appeared to "learn" that. I would like to have corrected him, but how could I have done so? Alternatively, is there a good education reason to teach this way, perhaps a "white lie" of some sort, to avoid overwhelming students with details?

$\endgroup$
1
  • 1
    $\begingroup$ And welcome to CSEducators. Bring your teacher here, too. You pose a common dilemma for students that is both thought provoking and fraught. $\endgroup$
    – Buffy
    Commented Mar 13, 2018 at 19:31

7 Answers 7

5
$\begingroup$

I've encountered experienced C and C++ developers who are convinced that Java is pass-by-reference for objects. One example I've used is this one:

void changeInt(int x){
  x = 42;
}

void changeString(String x){
  x = "hello world";
}

void testChanges(){
  int i = 0;
  changeInt(i);
  System.out.println(i); // still 0

  String s = "test";
  changeString(s);
  System.out.println(s); //still test
}

The changeInt() function fails to change the value of the parameter, because it's pass-by-value. But then the changeString() function also fails to change the value of the parameter- because it's also pass-by-value.

I also really like Cup Size -- a story about variables and its follow-up Pass-by-Value Please to explain the difference between pass-by-value and pass-by-reference from a Java perspective.

Now, as for whether you actually bring this up to your teacher, I'm not sure. If I were you I'd probably just bite my tongue and move on with my life.

$\endgroup$
3
  • $\begingroup$ Have you done this with other class objects, e.g. class Foo { int x; string s; } and changeFoo(Foo x){ x.t = "Hello World!"; }? $100 says that your original Foo now contains the string "Hello World!" $\endgroup$ Commented May 4, 2018 at 20:51
  • 1
    $\begingroup$ @Draco18s Okay, and I'm not sure what the point is? I'm only talking about changing the reference of the argument. Are you trying to say that your code proves that Java is pass-by-reference? Because it doesn't. $\endgroup$ Commented May 4, 2018 at 21:48
  • $\begingroup$ You make a great point! I think I need to incorporate it into my answer. In any case, I just voted yours up above mine. :-) $\endgroup$ Commented Oct 9, 2018 at 15:43
3
$\begingroup$

In an introductory Java class, I think it's fine to say that primitives are passed by value and that objects are passed by reference. That tells students what they need to know, although I might phrase it differently. (I'd say that primitives and references are copied when they're passed.)

In an upper-division programming languages course, I'd go into more detail about calling conventions and the full story about pass-by-value and pass-by-reference (and pass-by-name, so I can tell the joke about Niklaus Wirth), if there's time.

While I love for students to catch my mistakes and white lies, I think it might be nitpicky to do so in this case. If you feel a need to bring it up, go to the professor's office hours and express confusion reconciling what he said with what you've read online (perhaps citing a specific source). If he's a decent professor, he'll admit to having oversimplified or he'll accept the new knowledge.

Update

After reading Kevin Workman's answer, I see the problem with using the term "call by reference". I agree that no good can come from misusing that term. My second and third paragraphs still stand.

$\endgroup$
4
  • $\begingroup$ Of course, one hopes that the prof knows that she/he over simplified. Still, I'd warn the students at the time that I'm lying/simplifying/... $\endgroup$
    – Buffy
    Commented Mar 15, 2018 at 17:39
  • $\begingroup$ “For every complex problem there is an answer that is clear, simple, and wrong.” -- H.L. Mencken. There are too many Java tyros out there---some of them writing real-world, commercial code---who do not understand the difference between an instance and a variable. Telling them that Java "passes objects by reference" may be easier than telling them the deeper truth, but it does not help them in the long run. $\endgroup$ Commented Mar 16, 2018 at 2:31
  • $\begingroup$ Wait, so, what's the joke? $\endgroup$
    – Ben I.
    Commented Mar 16, 2018 at 2:53
  • 1
    $\begingroup$ @BenI., Read all the way down to the last sentence on the page. Niklaus Wirth... Call by name... Call by value... $\endgroup$ Commented Mar 16, 2018 at 13:26
2
$\begingroup$

The correct statement, of course is that Java passes a reference by value. That is not the same as passing by reference. You can easily show the difference, by assigning a new object to the parameter variable within the method and then noticing that the code that invoked the method doesn't see the new object. It would be pass-by-reference only if the caller sees the new object.

The confusion comes from the fact that the objects themselves are usually mutable and so within the called method, the receiver gets to make modifications. But both the caller and the called method have references to the same object. So the caller can see changes within the object made by the method. But it can't see a new object that replaces the parameter.

However, if you assign to the parameter variable within the method, then the caller and the called method will see different objects.

Yes, you should correct the teacher, but it is a bit risky, depending on the personality of the teacher. The best way, perhaps, is to prepare some demonstration code and show it to the teacher in the office. You can then, perhaps, offer to clarify the real meaning in Java, using your code.

Personalities can be messy, of course, and not every teacher likes to be contradicted. But the students have a right to know the "real deal" if they are going to program in Java.

Notice that Java and C++ are superficially similar, but deeply different. Learning both together is, itself, a cause of confusion. But in this case, the contrast can be informative.

If nothing else, you can show the teacher this post from a 40 year veteran of programming, much of that in OO languages, including both C++ and Java (and author of books in both).

$\endgroup$
1
  • $\begingroup$ It is amazing how many people get this distinction wrong, and how people can write correct code which, when you press them, their understanding contradicts completely! As always when this discussion crops up, I'll cite how much I love function definitions in FORTRAN, where you can explicitly state IN, OUT, or INOUT, and nobody has to worry about implicit semantics. $\endgroup$ Commented Mar 14, 2018 at 11:18
2
$\begingroup$

It may well be an intentional white lie. This suddenly reminds me back when over 20 years ago, in the department coffee room one professor said that it is better to flat out intentionally lie to oversimplify in the beginning. The students, overwhelmed with all these new and alien concepts already, cannot possibly have the capacity to follow and understand the complete truth at that point anyway. They must first understand the general and important ideas that we veterans take for granted and forget how difficult those ideas really are, before they are able to understand the nitty gritty details of the complete truth.

Back then the grad student me just couldn't understand why he would do that, although I did wisely hold my tongue. And now having taught intro Java myself for fifteen years, at some point I tell my students that I do exactly this, and one of these semesters (as usual, it is always the next one) I am going to carry with me one of those old time clicker counters and press it every time I tell such a white lie, and at the end of the course it should show a value of about thirty.

For example, in the beginning when we write the first classes and methods, I say something like "When you write a Java method, the order in which you write its statements is absolutely essential, because changing the order of two statements in a million line program could totally change the behaviour of not just that one method but the entire program. However, the order in which you write the fields and methods in the class can never make a difference to anything."

Click. Of course it can, since initializers are executed in the order of declaration. (And this order would probably affect the results of reflection also... but as I like to say in my classes whenever any questions of this nature spontaneously emerge, I type the question in Google search box and say "O Stack Overflow, enlighten us again with your wisdom" before pressing the return key to make students chuckle when I click the first link of the results page to read the Stack Overflow answer.) But at that point, it is enormously more important to make the students fully understand that methods are not executed in the order that they are written, but in the order in which the outside world invokes them. Any minor technical inaccuracy that I need to do to make them understand this is well worth the price.

Remember that we are dealing with people who need to be explained the difference between returning a value from the method versus printing it on the console.

When we get to arrays, I don't use the terms "pass by value" and "pass by reference", but simply say that when giving an array object as argument to a method, the method receives only the memory address where that array object is stored. The caller and the method therefore share the very same object, so any modifications that the method makes to the array object will remain there after the control has returned to the caller. And then compare the example methods

public int[] reverse(int[] a)

and

public void reverseInPlace(int[] a)

In the last lecture of the course, I go through a bunch of interesting and important and interesting little details that I tell them would logically have belonged to the earlier lectures, but at that point would have only confused them. But now, having worked through all my labs and listened to the previous lectures, they are ready to learn and understand them. One of those little details just so happens to be the computer science terms "pass by value" and "pass by reference" (and why not take a peek at Wikipedia page "Evaluation strategy" while we are at it, to give them a quick sneak preview of how programming paradigms other than that of Java really exist out there), which inspired me to write this response when I saw this question.

$\endgroup$
1
  • 3
    $\begingroup$ I have occasionally lied to students about some technical detail, but always, immediately, in the next sentence, tell them I lied so that they can note it and follow up when the truth is available. But you have to warn them, ethically. Misconceptions can be hard to erase and the follow up might be missed for one reason or another. So, if you lie, do it honestly. You should never put a student in the position of needing to unlearn something. $\endgroup$
    – Buffy
    Commented Mar 15, 2018 at 13:20
2
$\begingroup$

This is a tricky situation for you. You are correct that Java does not pass by reference, but your approach must depend on the personality of your professor.

If the prof seems like the sort of person who would warmly accept this sort of feedback, I might directly mention it to them. (I have done so, and it has been fine, though it often takes an exceptionally well-adjusted person to be able to take such feedback gracefully.)

A second option would be to raise your hand and ask about the difference between pass by reference, and passing references by value. This might trigger the prof to simply self-correct.

A third approach would be to email the professor anonymously. This is a generally a jerk move, and not recommended.

A fourth approach, which you have alluded to in your question, would be to pose the question as a pedagogic one. "Professor, I noticed that you told the class that Java passed Objects by reference. Was there some reason you didn't want to mention passing references by value? Was that just to avoid confusing people?"

As to whether there could be a pedagogical advantage to distinguishing the way that primitives and Objects are passed in a rough way, my instinct from years of teaching this topic is that there could be. I object to using the specific words "pass by reference" (because those words have a specific meaning, and don't apply here), but pointing out that there is a distinction right at the start is important. The behaviors of the two types of parameters will appear to be quite different to the beginner.

When I first introduce the topic, I simply want to call attention to the fact that something is going on here that the student needs to pay attention to, and I will be less concerned with whether every detail is understood at the start. Your professor could, indeed, be (somewhat clumsily) applying such a strategy.

$\endgroup$
1
$\begingroup$

The usual "explanation" like "Java passes primitive types by value and other by reference" is rather confusing.

In languages like C, C++, Fortran, etc. variables contain data. Then a variable is a chunk of memory with a name.

The explanation of parameter passing by value or reference) doesn't work well for languages (Java, PHP, Lisp, Python etc) where variables are names for references to data sitting somewhere in memory.

What is transmitted is the reference to the data. In all cases. The explanation fits well for primitive type : in

int n = 3;

consider n as holding a reference to an immutable constant integer value. And a call to foo(n) transmits the reference to that constant.

Of course, it happens that the variables of primitive types are not really implemented as variables containing references to objects. It's a tradeoff for efficiency in Java.

We'd better avoid using concepts which are pertinent for some - historically predominant - Fortran, Cobol, Algol, Pascal ...) langages to another category where they are much less adequate.

Not all languages have PICTURE and USAGE like COBOL. So we don't use these concepts to explain other programming languages.

EDIT: maybe the explanations about parameter passing focus too much on passing variables. I remember old-time FORTRAN where the statement

  call FOO(2+2)

could modify some constant in memory :-)

$\endgroup$
0
$\begingroup$

The proper way to think about this is to ask, "What is a variable storing?" Variables of primitive type store a bit pattern that represents their datum. Variables of object type store the memory address of the object they are pointing at on the heap.

When you pass a variable to a function, a copy of the value it holds is made and is placed in the function's local symbol table. This occurs whether the variable is of object or primitive type. Thinking this way, what we have here is pass by value.

If you pass a variable pointing at a mutable object and the callee invokes a mutator method, the state of the object residing on the heap will be changed. If the callee reassigns the variable, there is no effect.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.