16 ms·
Java is Pass-by-Value
- skocznymroczny 9y agoI argue with my coworkers often about it. I think the problem is that what Java calls references, works more like C/C++ pointer, rather than C++ reference. The name similarity but differing behaviour is what's confusing people.
- vbezhenar 9y agoNullPointerException :)
- froh42 9y agoThe exception was named like that before pointers in Java were called references. Urban legend says it was Sun's marketing department demanding Java sounds less dangerous than C/C++.
- michaelcampbell 9y ago> I argue with my coworkers often about it. I fail to see what possible value this has.
- chrisseaton 9y agoMaybe it's significant in their line of work? For example work involving Java semantics, such as language research.
- colanderman 9y agoPeople write incorrect code when they don't understand the semantics. I see this often in Python, especially surrounding its behavior with default parameters.
- alangpierce 9y agoPedantic arguments like this can be a good source of fun as long as everyone approaches it in a lighthearted way and acknowledges that it's pedantic. I could certainly see a conversation around pass-by-value/reference happening in my office, but if it got to the point of people getting angry at each other, that would be a sign that something is very wrong. When actually communicating with people for the purpose of conveying ideas (not just for fun), it's best to avoid terminology where not everyone has the same understanding of the definition. Open discussions about terminology are also a good way to identify these types of ambiguous terms and possibly come up with technical terms that everyone agrees on.
- ohf 9y ago> Java calls references, works more like C/C++ pointer, rather than C++ reference What makes you say this? You can't do pointer arithmetic on Java references, and the internal memory model is completely obscured. C++ and Java references look similar to and are accessed like variables. The major difference is that Java references can be reassigned, like a pointer, which is necessary in a language without true pointers.
- edflsafoiewq 9y agoIn C++, references aren't objects (eg. they have no size and no address), they can't be stored in a vector, there's no way to operate on the reference itself, everything is transparently forwarded to its referent, there is always a referent. In Java, a reference is a value, it can be stored in an ArrayList like a normal value, you can operate on the reference itself (reseating it, comparing two of them, comparing to null), there is not always a referent.
- ohf 9y agoTouche.
- colanderman 9y agoI always just call this sort of thing "pass-by-pointer-value" to clear up any confusion. To someone coming from C++, where objects are actually passed by value, saying that Java (or Python, or what-have-you) does the same is just confusing.
- andrewstuart2 9y agoAnother way of saying this is "reference by value." The people who say things are pass-by-reference when they're "pass by pointer value" have likely never worked with a true pass-by-reference language, and are just taking the phrase at its English face value.
- chi3 9y agoComing from C++, if "passing by pointer value" is considered "passing by value", then what is the opposite? Not passing at all? I mean, there's always going to be _some_ kind of value being passed?
- lmm 9y agoIf you write foo(&a), both "you pass a by reference" and "you pass &a by value" are fair descriptions of what happens. The confusion arises because Java doesn't explicitly distinguish between a and &a; if you write "Foo a = new Foo();" in Java, the behaviour is similar to "Foo *a = new Foo();" in C++. So if we ask how "a" is passed, is the "a" we're talking about the reference or the value?
- chi3 9y agoAh, I see the reasoning. I only did basic Java in university so I might be remembering incorrectly, but aren't variables storing non-primitive values called "References"? Seems weird to me to say that Java "passes by value" when all objects being passed are actually references to objects.
- lmm 9y ago> I only did basic Java in university so I might be remembering incorrectly, but aren't variables storing non-primitive values called "References"? Technically yes, but since the language doesn't let you talk about references directly, the concept rarely comes up. Like, in theory you could say "a is a reference that refers to a value of type Foo", but people don't actually say that; they just say "a is of type Foo". > Seems weird to me to say that Java "passes by value" when all objects being passed are actually references to objects. Indeed, completely agreed.
- quantumofmalice 9y agoThis comes up once every few years. The confusion comes from the fact that java syntactically hides the pointer for objects, which feel kind of like structs. It doesn't matter too much IMO. Most people intuitively understand how object references work in modern programming languages, and these discussions don't add a lot to their knowledge.
- catamorphismic 9y agoI actually find it is a pretty big and universal pain point while people are learning, particularly when switching languages.
- chris_wot 9y agoSo in that last example, someDog after you have finished the function foo() will be called Max... is this right?
- itronitron 9y agoYes, if you call the function like this, then Max will be the name of the dog when the function returns... Dog someDog = new Dog("Fifi"); foo(someDog); System.out.println(someDog.getName()); // name will be Max
- Nokinside 9y agoThese terms are so frustrating because they have "consistently wrong intuitive semantics" (I don't know better term). They are like cognitive puns. It's so easy to guess their meaning consistently wrong that people don't brother to look them up. When several people wrongly guess the semantics wrong exactly the same way and talk to each other, new meaning is established. It's not uncommon to have office debate of the difference where 9 people are sure that they know the right definition and the one person who argues for the right definition can't convince them. EDIT: there are already at least two comments that argue that the wrong definition is the right definition. These guys feel so strongly that their definition is right that nothing convinces them and people agree. It's a hopeless pursuit to get this right. https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value https://stackoverflow.com/questions/373419/whats-the-differe...
- colanderman 9y ago> It's so easy to guess their meaning consistently wrong that people don't brother to look them up. I find this to be the source of most programmers' confusion about most topics. Sometimes I spend hours arguing trying to convince someone that X works one way, because I've read the spec and the source code, while they believe that X works a different way, because they looked at its name and used it that way last time.
- xtrapolate 9y ago> "Pass-by-reference: The formal parameter merely acts as an alias for the actual parameter." "Alias" means nothing to a CPU, nor is it an ABI. At the core, passing by reference is usually implemented by providing the "address-of" something to a function (for example). The "address-of" itself, is passed by value. Going by that logic, everything everywhere is passed by value.
- asfasgasg 9y agoThis is the answer. Under the definition proposed in the article, all languages where the "=" operator can copy the values inside referents are "pass-by-reference." Languages where the "=" operator lacks that capability are pass by value. That is the only difference between swap in java and c++. In C++, operator= is a method over the value of the referent. In Java, you have to explicitly call that method. IMO it is a useless definition of "pass-by-reference," but the author is entitled to it. (With the exception of primitives. I guess that's the real rub -- Java's special casing of primitive values.)
- colanderman 9y agoIt is literally the definition of pass-by-reference. Your opinion does not change it. By the way, there is at least one additional difference in languages like Python and JavaScript with dynamic variable (not value) scope. In those languages, you can `delete` a variable, which removes the binding from the scope. Pass-by-reference would mean that you could delete a variable from a non-local scope if the variable were passed by reference. (This is not the case; `delete` in these languages merely deleted the local variable binding, as it ought, given that they are pass-by-value.)
- lmm 9y ago> It is literally the definition of pass-by-reference. Your opinion does not change it. Who died and made you secretary of the Académie anglaise? Language is defined by consensus; a word means x only to the extent that it is understood to mean x by both the sender and the receiver. This whole thread makes it pretty clear that "pass-by-reference" does not draw the distinction that you think it draws; if you want to draw those distinctions, find words that clearly draw those distinctions. Words are tools for communication, not ends in themselves.
- manaskarekar 9y agoHere is, what I thought, is an excellent video and the related article for Python: Ned Batchelder - Facts and Myths about Python names and values - PyCon 2015: https://www.youtube.com/watch?v=_AEJHKGk9ns https://www.youtube.com/watch?v=_AEJHKGk9ns Article: https://nedbatchelder.com/text/names.html https://nedbatchelder.com/text/names.html
- dep_b 9y agoI was looking for some kind of indicator when this article was written as the topic and style of design could be from the 90’s and the copyright goes from 1996 to 2014
- lisper 9y agoThis article is overly pedantic. Java's semantics are pass-by-value only of you consider that the "values" that are being passed are pointers. But Java doesn't have first-class pointers, it has implicit pointers. The only thing you can do with a Java pointer "value" is to tacitly dereference it. In fact, you can write a swap(x,y) function in Java. It goes something like this: class foo { int value } void swap(foo x, foo y} { int temp = x.value; x.value = y.value; y.value = temp; } (Yes, I know this isn't valid Java. Cut me a little slack here, OK?) "But that's cheating" you protest. "That's not swapping the value of X and Y, that's swapping the value of a slot in the values of X and Y, which happen to be objects." Well, yeah. So? Compare that to this C code: struct foo { int value } void swap(struct foo x, struct foo y) { [same code as above] } The effect of this function will be DIFFERENT. Specifically, the C function will have no effect while the Java function will swap the value slots of X and Y because C lets you pass a structure as a value while Java does not. All Java "values" are (tacit) pointers to objects [1]. Pounding your fist on the table and insisting that Java is pass-by-value because you can't write a swap(x,y) function obscures this crucial difference. [1] OK, it also has ints and floats of various sizes. But that's really it.
- colanderman 9y agoBut Java isn't pass-by-reference. Saying so is simply wrong, for exactly the reasons you write off as "pedantry". I see this play out all the time with co-workers who are new to Python (which has the same semantics) being very confused about why "numbers are passed by value but objects are passed by reference". Pedantry matters in our profession. Details have consequences.
- radicalbyte 9y agoIn C# you have an explicit syntax for passing a mutable pointer (i.e. a pointer to the pointer) so it's harder for people to get confused.
- lucio 9y agoThis is similar to relational algebra & relational databases. In relational algebra a "relation" is what most people know as a "table". "relation" is maybe a good name in the realm of relational algebra, but a bad name in the realm of users of relational databases. In this case "pass-by-value" and "pass-by-reference" are good names in the realm of compiler theory ("I'm a compiler guy at heart") but very, very bad names in the context of discussing parameter passing in java & objects.
- danharaj 9y agoA relation can't have multiple identical rows, but a table in most databases can, of course no primary key works for such a set of data and you can embed such a table into another table which has an underlying relation. Sorry, i agree with your point but I felt like being pedantic :3
- blattimwind 9y agoIf something is pass-by-value, but the underlying value primitive is not actually part of the language, we typically call this pass-by-object.
- jjnoakes 9y agoReference values are part of the Java language. It's the reason "==" doesn't do what you'd expect it to, and why "a = ..." inside a method (assuming "a" was a parameter) doesn't affect the caller.
- ThoAppelsin 9y agoWhile C++ is a whole lot of different language with operator overloading amd everything, I don't think the pass-by-reference in the C++'s way with &'s before the variable/parameter identifiers is much different from how Java handles the objects behind the curtains. In Java with no explicit pointers available to its users, the way objects are handled are explained better with the pass-by-reference concept than (whooosh!, magic in) pointers (and out) passed-by-value reality. Pointer is a foreign concept to Java, so it really makes more sense to its users that object variables start referring to other objects when they are reassigned, instead of the old object being changed in-place. Things get funky with equality comparison via == operator, but still, it is better than pointers. I also wonder, does C++ really pass-by-reference when parameters have &'s behind their identifier declarations, or does it internally pass a reference by value and dereference it every time it is used within that scope? Are 4/8 bytes allocated for the reference variable or not?
- colanderman 9y agoNo, it really is different. In C++ you can assign to variable references without additional syntax. You cannot do this (at all) in Java. I don't know what you mean by "really pass-by-reference". There is no such concept of a "reference" at the CPU level; nor is that relevant to language semantics. If you were to look at the generated assembly it would look identical to as if pointer referencing and dereferencing were used.
- ThoAppelsin 9y ago> I don't know what you mean by "really pass-by-reference". I was wondering if `int &a2 = a;` allocates memory in stack to make `a2` refer to `&a`, or does `a2` somehow truly become an alias for `a` in symbol table. As you've said that the assembly would look the same as pointers being dereferenced, then I suppose C++'s reference types are just a syntax sugar around the C's way of achieving the pass-by-reference concept through passing the address and then dereferencing it.
- chi3 9y ago
- sorokod 9y agoThere are two levels of misunderstanding to this discussion: 1. The way parameters are actually passed in Java, primitives by value, object references by value. 2. How to call this mechanism. My guess is that many fail on item 1. Once understanding of item 1 is achieved, item 2 isn't terribly interesting.
- dgreensp 9y agoI don’t see why C++ “references” should have a monopoly on the term “reference," such that a language calling anything else a reference is making an error. C++ references are actually kind of a weird/unusual language feature that isn’t being taken up by other languages. I don’t see cause for reserving a term for them. Each language can decide what it is going to call a “reference.”
- ohf 9y agoJava references are closer to C++ references than anything else. They're like pointers until you access/call them, at which point they're just objects. C++ references are identical, but the syntax is a bit more explicit. It is a funny language feature to have when you think about it; it just so happens to be useful. References and pointers are distinct in languages that have both (C++), so not mixing the terms between languages is helpful. If Java programmers started referring to their variables as "pointers," because internally, that's more representative of what they are, I'd be a bit irked.
- jholman 9y agoIt's not that other languages don't have references, or that they cannot redefine references. It's that the phrase "pass by reference" is a term of art in compiler design, and all language theorists including those who work on Java agree on what it means, and what it means is the thing the article says it means, and Java doesn't do it. What gets passed by value in Java? Well, sometimes it's a reference-as-Java-means-it! But that reference is always passed by value, never passed by reference.
- crehn 9y agoTLDR: objects are not passed by reference; object references are passed by value
- itronitron 9y agopro tip: objects are never passed, object references are :)
- SigmundA 9y agoHaving started off doing VB programming and now .Net and Javascript with some C mixed in this all seems like second nature to me. C# is somewhat more clear to me because it lets you do either, which VB kinda did too. The key point here is reference types vs value types, which is distinct from pass by reference and pass by value. Java is pass by value only with reference types and primitive value types. C# has reference types and value types and pass by value default with pass by reference optional. passing a reference type by reference is passing a pointer to a pointer. See: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
- kstenerud 9y agoThe fact that so many people get this wrong yet are so sure they're right is indicative of a U/X issue. Fix the nomenclature and you'll fix the problem.
- zzzcpan 9y agoIt's not really a UX problem as these things are not actually used. We just can't agree with each other what the nomenclature should be and it's this way precisely because there is no real use for the nomenclature.
- reikonomusha 9y agoOr it’s a reflection of a lack of rigorous training. Lots of folks like to infer and consequently assume without reading.
- gvx 9y agoThat, and I don't think there is a real consensus on the nomenclature, even in the literature. At least, I don't remember university lectures being at all clear on the issue. FWIW, I don't use pass-by-value or pass-by-reference to refer to languages like Java, Python, Lua, etc... Instead, I use "pass-by-object-identity" (aka "call-by-sharing", "call-by-object") to refer to the semantics of those languages. It avoids the association many people have between the term "by-value" and copying behaviour. Also part of the problem: many beginning and intermediate programmers don't understand the difference between rebinding and mutation. This leads to people interpreting the following snippet: def foo(a, b): a = 2 b.append(3) x = 1 y = [] foo(x, y) print(x, y) #1, [3] ... as meaning that ints are passed by value and lists by reference, while in fact both are passed by object identity, and it is the fact that a is rebound while b is mutated that made the difference.
- stephengillie 9y ago"Create-copy" and "create-alias" are better ways to describe the concepts. This post describes pass-by-value as create-copy, and pass-by-reference as create-alias. Create-copy - Copies the data into a new memory location, so modifying this variable will not modify the original variable. Create-alias - Creates a new name for the same memory location, so modifying one variable will also modify the other variable. Having spent too much time in Powershell, which defaults to create-copy, it was jarring to switch to Javascript and the seemingly-non-deterministic behavior of create-alias on setting a new variable equal to an array. From an algebraic perspective, when I modify "foo", I expect "bar" to remain the same.
- Zarel 9y agoThe confusion comes up when you do a _shallow_ copy: Some modifications will modify the original variable, and other modifications won't. Pass-reference-by-value is just a special case of a shallow copy. let a = [1, 2, 3]; let b = a; b[1] = 5; // will modify a b = [1, 6, 3]; // will not modify a In languages like C++, there's a way to make it so that last line _would_ modify a, which is why there's a need to use different words for the different phenomenon.
- TazeTSchnitzel 9y agoThis is a problem in PHP, which has both primitives (including copy-on-write arrays) and Java-style objects, but it also has literal pass-by-reference referencing (you can write a swap function). The misuse of “pass-by-reference” here creates confusion.
- cup-of-tea 9y agoI thought this was common knowledge. I was taught that Java is pass-by-value in compiler-writer terms, but as a programmer you can think of it as pass-by-reference because you have no control over it.
- Terr_ 9y agoI believe the difficulty with "pass by reference" is that the phrase implies (at least in other languages) that the function-body can potentially alter variables in the caller's scope, by assigning something to the parameters it is given. In other words, "C-style" pass-by-reference means this function would have an undesirable side-effect: void foo(Thing x){ x = null; }
- tunesmith 9y agoIs it bad to completely ignore this behavior? For instance, something like: Dog d = new Dog("fido"); d = alterDog(d); public Dog alterDog(Dog d) { d.name="arfybark"; return d; } It's not quite a pure function since it changes it in place, but at least the parameters and return types reflect the method. I ran across a term for this practice in the past but don't remember what it's called.
- ohf 9y agoI would actively avoid that, but only because it confuses me. That syntax loosely implies that removing the second d assignment would allow me to create new-but-altered dogs with alterDog(Dog), which isn't the case. If I wanted to use assignments like that, I would try to go fully immutable with factory methods that help me make slightly different, new dogs on the fly, and return them.
- catnaroek 9y agoJava is pass-by-value, indeed. Too bad Java's values aren't the values you want.
- bullen 9y agoJust makes me think of how I learned to code this in C++ with array pointer by reference and/or value (still don't know and really don't care ;) int dosomething(int * & array) {} That * & is just complete voodoo magic.
- colanderman 9y agoThere's a lot of confusion in this thread about what "call-by-reference" means. Let's be very clear. If Java were "call-by-reference", then this function: static void foo(Object x) { x = null; } would have an effect visible to the caller. This is exactly the case with C++ references, and C and Lisp macros, which are call-by-reference. (C++, C, Lisp, and the term "call-by-reference" all having existed prior to Java, by the way, so Java and its users do not get to redefine it.) But the above function does nothing in Java. Hence, Java is not call-by-reference. Wikipedia has a nice quote [1] from Barbara Liskov (the namesake of the Liskov substitution principle), made when she invented the passing style used in Java in 1974, for use in her language CLU: "In particular it is not call by value because mutations of arguments performed by the called routine will be visible to the caller. And it is not call by reference because access is not given to the variables of the caller, but merely to certain objects." She settled on the term "call-by-sharing". Maybe we should all just agree on that. [1] https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sh...
- slowmovintarget 9y agoShould probably be tagged [1996] as this article hits HN roughly once a year. A good read, if one hasn't encountered it before.
- emh68 9y agoIt’s a VM language and therefore “pass by value” and “pass by reference” don’t make sense in this context. But people love to subdivide everything into two groups so have at it, who am I to rain on your party.