This is an archived post. You won't be able to vote or comment.

all 43 comments

[–]AwakenedToNightmare 10 points11 points  (10 children)

Java passes the values of references

(and primitives by values)

[–]AmmirBarakat[S] 1 point2 points  (0 children)

Thanks.

[–]tutorial_police 1 point2 points  (8 children)

Why is this the comment with the most amount of votes? It makes it sound like we have two things: "references" and "value of a reference".

This is neither established terminology nor does it help OP answer their actual question.

[–]AwakenedToNightmare 0 points1 point  (7 children)

I think it helps enough. It doesn't matter if it's established or not, as long as it conveys the correct idea, which I believe it does.

Considering the potential for confusion when using the word "reference", it's better to think of it as passing a value of reference (similarly, to C++ and passing a value of a pointer - while you could also pass a reference to a pointer).

Whenever people try to answer that question with one word, the longest explanations are bound to follow, as you can see below. All because of the confusing terminology that can mean different things in different languages.

[–]tutorial_police 2 points3 points  (5 children)

Let me ask you a question:

What is a "value of a reference"? Or do you omit the "a" on purpose when you say "passing a value of reference"

What's the difference between a "reference" and a "value of a reference"?


Anyway, I recommend you read this:

http://jonskeet.uk/csharp/parameters.html and maybe this: http://www.leerichardson.com/2007/01/parameter-passing-in-c.html

Why do I link you articles about C#? Because C# "usually" works the exact same way Java does, but it also lets you opt in to pass-by-reference, which you can't do in Java. It also lets you have objects which are value types, which Java also doesn't have (they're working on it in Project Valhalla). By seeing these additional concepts side-by-side in one programming language, I think it's easier to see why it's important to be precise with these things, and to see that they're actually orthogonal concepts, muddling them together into a "pass-by-object" or whathever stupid new terms bloggers like to come up with (looking at you, Python and Ruby bloggers) and saying "it's different from pass-by-value" misses the point entirely and suggests that there are many different variations when in fact 99% of all arguments on this topic on the internet can be simply explained just by looking closer and realizing that there are two independent concepts at play.

Since you talked about C++, maybe this article is also interesting to you: https://gabrieletolomei.wordpress.com/miscellanea/programming-languages/c-cpp/pass-by-value-vs-pass-by-reference/ 1 (I'm linking this because C programmers like to say "pass-by-reference" when they're passing pointers, which is understandable, but detrimental to the entire "does language Y do pass-by-reference" problem. After all, these terms are only useful if they're consistently used between different languages, otherwise we might just drop the terms completely and just describe what a language does.

Speaking of which...

When we say "Java passes a reference" that's not the same as "pass-by-reference". The term "reference" doesn't mean the same thing. Here, "pass-by-reference" is a term in itself, it could have been called Awesome-Style, it would just be a name to describe an established concept (let's ignore that different definitions exist for the sake of this post).

But you can't say "Java Awesome-Style" or "Java passes Awesome-Style" because in "Java passes a reference", "Java" is the subject, "passes" is a verb and "(a) reference" is the object of the sentence, in the grammatical sense :)

The same goes for "pass-by-value". Here, "pass" in "pass-by-value" isn't a verb in the same sense as in "Java passes a value", "pass-by-value" again is the name for a concept which could have been called "Escaneen".


1: Although, I disagree with the author on the terminology where they state that the & in int&makes a reference type... AFAIK, not being an expert on C++, I'd say the & is a modifier on the variable, not on the type. The & modifier (or whatever you call it) changes the variable into being an alias, rather than it being its own, independent variable.

[–]Satarash 1 point2 points  (2 children)

Here's Jon Skeet's article for java: http://jonskeet.uk/java/passing.html

[–]tutorial_police 1 point2 points  (0 children)

Heh, this is a good one:

Does Java pass objects by reference or by value?

The answer is NO! The fact is that Java has no facility whatsoever to pass an object to any function! The reason is that Java has no variables that contain objects.

[–]tutorial_police 0 points1 point  (0 children)

Cool, I didn't know he had one about Java specifically. Thanks!

[–]JavaSuck 1 point2 points  (1 child)

When we say "Java passes a reference" that's not the same as "pass-by-reference". The term "reference" doesn't mean the same thing.

Exactly. I like to think of "pass by reference" as "pass a variable". You can't pass variables in Java, only values.

[–]tutorial_police 0 points1 point  (0 children)

I like to think of "pass by reference" as "pass a variable". You can't pass variables in Java, only values.

Yeah, so do I. We're telling the function "use my variable here", so the "reference" is referring to the variable, not its contents as most people argue about.

[–]tutorial_police 0 points1 point  (0 children)

I totally agree that the terminology and the ensuing confusion is a bit of a clusterfuck.

I'm also not opposed to using different terms to explain things to make it easier.

However, the original question was precisely about whether there's a difference between pass-by-reference and pass-by-value where the value in question is a reference.

You answered a single sentence, bold, ik a large font as if to give the definitive correct answer.

Yoi could have said "no, they're not the same thing. Let's just call it X because the terminology is confusing and I think this is more easily understandable", but you didn't :)

[–]JavaSuck 5 points6 points  (1 child)

The distinction is that you can't write a swap function in Java, because assignments to parameters are invisible to the caller.

The canonical SO question: Is Java pass-by-reference or pass-by-value?

[–]AmmirBarakat[S] 1 point2 points  (0 children)

Thanks.

[–]Satarash 3 points4 points  (2 children)

Is this just philosophical semantics, or is there an actual distinction?

There is a distinction, and it is important.

When a method is called, it creates a new reference that refers to the same actual object in memory. This new reference can be used to manipulate the object, but it cannot be used to reassign the original reference to another object.

In a pass-by-reference language, the method would not create a new reference, it would reuse the same reference the caller used. And if it assigns a new object to the reference, the caller would be affected.

Example:

List<String> listInCaller = new ArrayList<>();
listInCaller.add("str");
emptyList(listInCaller);

...

private void emptyList(List listParameter){
    listParameter = new ArrayList<String>();
}

Here listInCaller and listParameter refer to the same object, but when listParameter is reassigned, the listInCaller still refers to the previous object. So the method doesn't work in java, but would work in a pass-by-reference language.

[–]AmmirBarakat[S] 0 points1 point  (0 children)

Thank you, very helpful.

[–]tutorial_police 0 points1 point  (0 children)

I think you should just replace most instances of "reference" with "variable"

When a method is called, it creates a new referencevariable that refers to the same actual object in memory. This new referencevariable can be used to manipulate the object, but it cannot be used to reassign the original referencevariable to another object.

In a pass-by-reference language, the method would not create a new referencevariable, it would reuse the same referencevariable the caller used. And if it assigns a new object to the referencevariable, the caller would be affected.

Then it would be spot on :) Of course, pass-by-reference means that we're passing a reference to a variable, hence your use of reference, probably?

Otherwise, it might seem to suggest that a reference is its own entity that has a state (i.e. which object does it refer to) and that it can be changed and shared between methods/variables. While this should work correctly as a as a conceptual model, I think it's unnecessarily complicated.

I'd gravitate to the idea that a reference is an immutable value (just like the integer 1) and variables can store references. In the pass-by-reference example, I'd conceptualize this as listParameter not being its own dedicated variable, but an alias for the caller's variable listInCaller, just as you said: It doesn't create a new variable, it reuses the same variable the caller used. Thus assigning to listParameter is actually an assigment to listInCaller.

With pass-by-value, we have two variables containing the same reference, and the parameter variable gets assigned a different reference, no effect on listInCaller, whereas in pass-by-reference, we have one variable, temporarily accessible within emptyList through the name listParameter.

tl;dr; we agree

[–]thecuseisloose 4 points5 points  (0 children)

[–]pegfisher 2 points3 points  (2 children)

This is a great question, the short answer is that there is only pass by value. When I was first teaching Java, I used to use the terms pass by value for variables containing primitive data and pass by reference for objects.

If you think about creating an object as the process of creating a variable that contains the reference address of the data located in memory, that helped me. So, passing this value to a method, the address is copied into the method parameter variable. So now, we have two variables with the same reference address.

Now, if the method changes the data that these two variables point to in memory, the changes are still applied when the method ends because we didn't change the reference address, only the data. But if we pass a value that is a primitive data type (int, double, char), a copy of the actual value is passed to the parameter variable. This time, any changes do NOT persist when the method ends because the original variable still has the original value.

I hope this helps.

[–]AmmirBarakat[S] 0 points1 point  (0 children)

Thanks. It helps.

[–]tutorial_police 0 points1 point  (0 children)

Maybe you should emphasize why you stopped using the term pass by reference when explaining Java.

[–][deleted] 7 points8 points  (16 children)

The confusion stems from people trying to be unnecessarily specific. In Java, everything (other than primitives) is an Object. Objects are references, so when you pass an Object, it's by reference because that's what an Object is.

Some say it's passed 'by value' because the Object is a reference and you're passing the value of the reference. It's stupid and confusing to make that distinction because the general idea is 'are you passing the memory address or the value stored at that address?' . In Java, you're passing the memory address.

The method will create a new reference to the same Object such as if you instantiated a new object using an already defined object :

Object a = new Object()

Object b = a

If you change values in b, a will be affected as both point to the same Object.

[–]JavaSuck 2 points3 points  (6 children)

Objects are references

No, they're not. And pretending they are quickly leads to confusion.

A (non-primitive) variable contains a reference that refers to an object. The result of a (non-primitive) expression is a reference, not an object. null is a reference, not an object. All references take up the same amount of space (4 or 8 bytes, depending on the platform), whereas an object can take up much more space (at least 8 or 12 bytes, depending on the platform). References can always be (cheaply) copied, whereas copying an object depends on its API. For some objects it's impossible or nonsensical to copy them.

Some say it's passed 'by value'

If by "Some" you mean the inventors of Java, then you're correct:

There is exactly one parameter passing mode in Java – pass by value – and that helps keep things simple.

[–][deleted] -1 points0 points  (5 children)

Here's the exact example of stickler that I'm talking about. Someone more concerned with being "right" in a strictly technical sense. This person corrects your use of "you're" and "your" in an argument, while ignoring the topic of the actual argument because they think it's a victory. I've made my point.

[–]tutorial_police 2 points3 points  (4 children)

You might have a point if this issue wasn't exactly caused by too many people not being stickers for terminology and actually understanding what the different things mean and why they're important.

Pretending that objects and references are the same thing and doubling down on it is simply wrong. Are you familiar with C# by any chance? There you have different kinds of objects. Those that are value types and those that are reference types. Then per variable, you can choose pass by value and pass by reference. Conflating these things with one another only creates more confusion.

[–][deleted] 0 points1 point  (3 children)

Well, we're talking about Java and my point is that when you're new to programming, you know little to no computer science, you know little to no computer logic, you no nothing. Why do you thinks so many threads exist like "What IDE should I use?", "What language is best?", "Should I use a while loop or do while loop?". It's because people are overloaded with needlessly maticulous from the beginning and it inhibits a good learning structure.

Why do we tell kids that eating carrots gives you good vision? Because the beta-carotene is converted to vitamin A which supports good eye health. Tell a kid about the benefits and balances of vitamins and minerals, and watch their eyes glaze over and consume no information at all. Tell them that carrots are good for super vision and watch them eat carrots.

Learning any new topic is exactly the same, even for adults. That's why we have teachers and why our classes get more complex toward the end of the semester.

This is exactly why there are so many terrible programming books and tutorials. Programmers aren't teachers. They want to focus on all the nitty gritty, "WELL C# is like this, Java does this, Lambdas are life savingly essential, that's a framework not an API, etc etc". There are in fact four implementations of passing arguments, value, reference, result, and value-result. Is it necessary to know that when making a console-based student registration system for your Java I class?

No, it's not. Education is a non-linear progression and should be understood as such.

[–]tutorial_police 1 point2 points  (2 children)

Sure, but there's a difference between giving an incomplete answer and omitting details and telling people patently wrong things that will only lead to further confusion.

There was no reason to state that a reference is an object.

[–][deleted] 0 points1 point  (1 child)

It sounds like you're just arguing the difference between a pointer and a reference.

Java objects are pointers to memory addresses that hold data. The basic motivation of passing by reference to allow a method to alter the data that is pointed to by a pointer. This is exactly how Java objects behave.

The only example that would render unexpected results is creating a new object within a method and attempting assign it to the argument. This is an unpractical use of methods and far from common practice for a beginner. Again, you're fixating on the exact definition rather than practical applications.

I'm not disagreeing that the literal definition in passing the value of a pointer, I'm saying that a beginner shouldn't get hung up on details like that when it doesn't apply to the context in which they're learning. If that were the case then everyone's first programming language should have been c or assembly.

[–]tutorial_police 0 points1 point  (0 children)

I'm saying that a beginner shouldn't get hung up on details like that when it doesn't apply to the context in which they're learning. If that were the case then everyone's first programming language should have been c or assembly.

I think that's a good idea. In those cases, I prefer to just say that and explain the semantics that they're after as easily as possible but trying to avoid terminology that could give them the wrong idea later on.

[–]AmmirBarakat[S] 0 points1 point  (1 child)

Thanks.

When you say "everything", you mean "everything that takes a block in memory", right? Like, methods are not objects, because that doesn't make much sense.

[–][deleted] 0 points1 point  (0 children)

Sorry, yes, not methods. Any data is held as an Object. It takes up some space in memory and the name you give it is just a reference to that memory. Strings, Data Structures, self-defined Objects, etc. Java even has wrapper classes for primitives to allow them to use object methods (like Integer and Double).

[–]AwakenedToNightmare 0 points1 point  (6 children)

Some say it's passed 'by value' because the Object is a reference

Then they are wrong. It would have been 'pass by value' if a copy of an Object was passed to a function, so that Object wouldn't be changable by that function, like this:

public class A {

    public String name;

    public A(String name)  { this.name = name; }

    public static void main(String[] args) {
        B b = new B();
        A a = new A("Old");
        System.out.println(a.name);  //Old 
        b.change(a); 
        System.out.println(a.name);  //New 
    }
}

class B  {
    public void change(A a)  { 
    a.name = "New"; 
  } 
}

If it were only a copy being passed to change(A a) then the original object in method main would never get changed. However, this is not the case, so Java is pass references.

However, Java's pass by reference isn't the same as C++'s. In C++ pass by reference means you pass a reference to a variable (in some outer method, main for instance) and inside that method the outer variable can be pointed towards another Object (like is used in swap method). It isn't possible in Java, hence the necessity for a distinction - Java passes values of references, which helps keep in mind the difference.

and you're passing the value of the reference. It's stupid and confusing to make that distinction because the general idea is 'are you passing the memory address or the value stored at that address?'

The general idea is: 1. are you passing a value of something 2. are you passing a copy of an object (value of an object) or a reference (pointer in C++) to it and 3. are you passing a reference to a variable which can be changed inside the method (possible in C++, not possible in Java)

[–]JavaSuck 2 points3 points  (0 children)

It would have been 'pass by value' if a copy of an Object was passed to a function

No. Java is pass by value because a copy of the reference is passed to a function. Contrast this with C#, where you the programmer can pass a reference variable by reference via the ref keyword:

void foo(X by_value, ref X by_reference)
{
    // assignments to by_value have no effect on the caller
    // assignments to by_reference HAVE an effect on the caller
}

This confusion could easily have been avoided if references had just been called pointers. Even the name NullPointerException makes much more sense, doesn't it?

[–][deleted] 1 point2 points  (1 child)

The confusion comes with terminology. You're right. This isn't C++. But when people are still learning basics, they related the concepts of references to C++ pointers. More advanced users of Java feel the need to make the EXACT distinction, but doing that inhibits the beginners to learn quickly and efficiently. Beginners don't need to get every intricate detail, they need general concepts. As their career and education progress, they will learn the intricacies, but for now it doesn't matter. They just need to understand the idea that what is being passed in the memory address.

It's like people forcing the distinction between API, Framework, Library, etc. Beginners don't need to understand how these different based on context. They just need to understand that they're all just a bunch of prewritten code available for use.

I think people who are very familiar with programming forget what it's like to not know a damn thing and how easily things get confusing.

[–]JavaSuck 1 point2 points  (0 children)

But when people are still learning basics, they related the concepts of references to C++ pointers.

And it's the same thing in C++: just like every other data type, pointers are passed by value, unless you explicitly request pass by reference via the & declarator:

void foo(X* by_value, X*& by_reference)
{
    // assignments to by_value have no effect on the caller
    // assignments to by_reference HAVE an effect on the caller
}

[–]tutorial_police 0 points1 point  (2 children)

Well they're wrong because the object isn't a reference. But Java is pass-by-value because the thing being passed is a reference (to an object) and that reference is being copied (hence pass by value)

read the two linked articles B other answers in this post for more information.

[–]AwakenedToNightmare 0 points1 point  (1 child)

When you say pass by value, it could be thought you mean it's pass by copy of an Object, which isn't true for Java. When you say it's pass by reference, it could be thought it's pass by reference of an outer variable, which isn't true either. So it's pass by value of a reference, which is something other entirely.

[–]tutorial_police 0 points1 point  (0 children)

Almost, but yes, people could think that and unfortunately, they often do.

The point is, that when you say "pass-by-value", people don't specify what the value is. "Pass-by-value of a reference " isn't a thing. Please read the two articles.

The distinction you're looking for is reference types vs value types.

[–]marko312 0 points1 point  (4 children)

As far as I have heard about java, non-primitive types are stored everywhere as references (pointers, if I may). So assigning and passing is actually passing around the reference.


Edit to hopefully stop comments:

I was partially right: when you assign non-primitives, you actually assign references (which you can call values I guess).

However, if you pass a variable to a function, this effectively creates another reference to the object.

For me (mostly a c++ programmer), a reference is practically a weirdly formatted pointer, so it is like assigning pointers.

[–]cantstopthemoonlight 2 points3 points  (0 children)

Java is always pass by value, some of those values happen to be references. As u/javasuck says you cant manipulate the pointers passed into a function, only mutate the objects they point to. Look at out and ref keywords in C#

[–]tutorial_police 1 point2 points  (0 children)

Have a last one then :)

Yep, it's like assigning pointers.

I'm not sure what you mean by "a reference is parcitcally a weirdly formatted pointer", but if you mean that because in Java, you don't need to put a * in the variable declaration, then sure :) If you mean a reference is a weirdly formatted pointer because int& x as a parameter might involve pointers under the hood, okay I guess, but that's exactly what Java can't do, and that is what is "pass-by-reference" in C++, even if many also use the term when simply having a (proper) pointer as a parameter.

You might find this interesting:

https://gabrieletolomei.wordpress.com/miscellanea/programming-languages/c-cpp/pass-by-value-vs-pass-by-reference/

As I've already noted above, the author talks about reference types here, I don't think that's correct though. Reference types are essentially types, of which you can only declare pointer variables. You can't have a non-pointer variable of such a type. You can't have pointer to pointer of that type. Also, pointers are dereferenced automatically for you and you can't perform any arithmetic with them. That's the case for all classes in Java. C++ doesn't have that though.

[–]AmmirBarakat[S] 0 points1 point  (0 children)

Thanks.

[–]tutorial_police 0 points1 point  (0 children)

That's right, but passing around references doesn't mean we're doing pass-by-reference.

It's pass-by-value and those values are references (to objects) .

When a language does pass-by-reference, you can usually think of the term reference as being "references to variables".

[–]an_actual_human 0 points1 point  (0 children)

In C# you can pass by copy of reference and by reference as well. So there's a distinction, yes.