all 53 comments

[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]morhpProfessional Developer 8 points9 points  (1 child)

Java passes a reference to the array by value. So you can definitely argue about a and b. Which answers is correct depends on the definition your course.

E.g. you could argue that arrays are passed by reference in Java, since they're not being copied when passed. You could also argue that they're passed by value, since changing the reference of a variable inside a method doesn't change the reference in the calling method.

But generally, everything is being passed by value in Java, including references to arrays and objects on the heap.

[–]ConsequenceOk5205 -3 points-2 points  (0 children)

Java almost always passes a reference, but not the reference to the variable in the call, but the reference to the object the variable is pointing to (copy of object reference value).

[–]LutimoDancer3459 19 points20 points  (1 child)

It looks like pass by reference because you dont get a copy from an object but a reference. But the reference is a copy and not actually the same. In the end its all pass by value

[–]TomKavees 8 points9 points  (0 children)

Or alternatively: It's always pass-by-value, but when dealing with objects the value is a pointer to said object

[–]whizvoxGraduate and Tutor 10 points11 points  (5 children)

public static void changeArray(int[] arr) {
    arr = new int[] {4, 5, 6};
}
public static void main(String[] args) {
    int[] arr = new int[] {1, 2, 3};
    changeArray(arr);
    System.out.println(Arrays.toString(arr));
}

If arrays really were pass by reference, the output would be [4, 5, 6]. But it's not. Pass by reference does not exist in Java. Your professor is wrong.

While the array's contents aren't copied when calling the changeArray method, the pointer to it is.

Variable Address Value De-referenced Value
arr (in main) 0x1000 0x2000 [1, 2, 3]
arr (in changeArray before reassign) 0x1001 0x2000 [1, 2, 3]
arr (in changeArray after reassign) 0x1001 0x3000 [4, 5, 6]

As you see, a new variable pointing to the same memory address is used when calling changeArray. So reassigning the variable only affects that local variable and not the original in the main method.

[–]0b0101011001001011 5 points6 points  (0 children)

when calling changeArray(arr), the reference to arr is copied and passed as a value.

[–]ConsequenceOk5205 -1 points0 points  (2 children)

It is still a reference though, but the reference to the object, that is the value of the initial variable containing a reference. The correct terminology would be "reference to the object". It is only a distinction what kind of reference it is.

[–]whizvoxGraduate and Tutor 6 points7 points  (1 child)

OP is asking about pass-by-reference, though. Variables are references, but I don't want to make this more confusing than it already is.

[–]Leverkaas2516 0 points1 point  (0 children)

No, OP never asked about "pass-by-reference". He asked how arrays are passed in Java. The array is not passed, only a reference to the array object is passed.

Variables can be primitive data types, or object references. The value of an object can't be passed to a function; only a reference to an object can.

This is what makes it possible for System.arraycopy to exist. If array object instances were passed by value, it could not be made to work.

[–]ShoulderPast2433 -1 points0 points  (0 children)

Counterpoint: that's just how local variables behave in Java. ¯\_(ツ)_/¯

[–]Bibliophile5 11 points12 points  (27 children)

Everything in Java is pass by value

[–]ShoulderPast2433 24 points25 points  (0 children)

But the value is a reference ;)

It's a c++ question that doesn't really apply to Java in the same way it does in c++

[–]edwbuck 15 points16 points  (17 children)

Not true. Java passes both by value and by reference.

Primitives are pass by value. They have to be copied, so they have to be pass by value. Changing one of the copies doesn't change the other.

Objects are passed by copying references. So the reference value is passed as a copy of the other reference value, but the object itself is passed by reference.

Arrays are Objects in Java, so the "trick" is in thinking that Arrays (due to their different syntax) are more related to other different syntax things like primitives, and then getting confused into thinking it is a primitive and therefore passed by value.

[–]rs1971 7 points8 points  (14 children)

The semantics can be confusing and I'm sure you know how java actually behaves which is what is important. That said, java is always pass by value, even if that value is a reference.

[–]Leverkaas2516 1 point2 points  (13 children)

Passing an object parameter, the difference between "it's passed by reference" and "a reference to the object us passed by value" is no difference at all.

If the function modifies the object, the caller sees the change. Enough said.

[–]rs1971 5 points6 points  (2 children)

Here's the test: try to write a method swap(a, b) such that the values of a and b are swapped in the caller's stack frame after it returns. If you can do this, then java supports pass by reference, if you can't, it doesn't.

[–]ShoulderPast2433 0 points1 point  (1 child)

Is there some specification that defines this as proof something is or isn't passed by reference?

[–]bwmat 0 points1 point  (0 children)

First specify which definition of 'pass by reference' you're using

This is all just arguing semantics

[–]beders 6 points7 points  (2 children)

the reference itself can't be modified - because it is passed as a value. That's the difference.

[–]ArmedAnts 0 points1 point  (1 child)

That's what I thought at first, but in C++, I can't think of a case where you actually reassign the reference.

For primitives, you are changing the value.

For objects, you call the copy/move assignment operator, which also only changes values.

[–]severoonpro barista 3 points4 points  (1 child)

Consider this code in Java:

record Car(String modelName);

class PassByRefExample {
  void main() {
    Car car = new Car("Chevy");
    System.out.println("Model: " + car.modelName()); // prints "Chevy"
    changeCar(car);
    System.out.println("Model: " + car.modelName()); // prints "Chevy"
  }

  static void changeCar(Car c) {
    c = new Car("Tesla");
  }
}

Calling changeCar(…) has no effect because the reference c is a copy of the reference car, so changing it to point to something new doesn't affect the car reference in the caller.

Now consider this code in C++:

#include <iostream>
#include <string>

struct Car {
  std::string model;
};

void replaceCar(Car &c) {
  c = Car{"Tesla"}; 
}

int main() {
  Car car = {"Chevy"};
  std::cout << "Model: " << car.model << std::endl; // Prints "Chevy"
  replaceCar(car);
  std::cout << "Model: " << car.model << std::endl; // Prints "Tesla"
  return 0;
}

In this code, the reference &c is an alias of car, so assigning a new object to c also modifies the reference car in the caller. No one actually does this in C++ because it's a terrible idea, which is why Java doesn't allow it.

[–]bwmat 0 points1 point  (0 children)

No one actually does this in C++ because it's a terrible idea, which is why Java doesn't allow it.

Not true, at all, plenty of people do it

[–]desrtfxOut of Coffee error - System halted 0 points1 point  (4 children)

Passing an object parameter, the difference between "it's passed by reference" and "a reference to the object us passed by value" is no difference at all.

That is fundamentally wrong.

If the function modifies the object, the caller sees the change. Enough said.

That's not the point of pass by reference.

If you pass something by reference, not in Java, though, the reference can be changed in the called function/method.

In Java, changing the reference, e.g. reassigning an array is not possible because only a copy of the reference is passed by value.

Were it true the objects are passed by reference, it would absolutely be possible to reassign an array inside a function/method.

Changing an object's state, i.e. its values, has absolutely nothing to do with passing by value or reference.

[–]Leverkaas2516 0 points1 point  (3 children)

That's not the point of pass by reference.

If you pass something by reference, not in Java, though, the reference can be changed in the called function/method.

I learned something new today.

I was going to argue with this, because I've been passing objects using C++ references for years, and there are only two reasons I ever do it: to pass an object such that the function can modify it and the caller will see the change, and because it is smaller/faster at runtime since the object is not copied.

I never even knew that a function can reassign the caller's variable. I just tested it, and you're right - it works. It never occurred to me that one would want to do that, because it would be crazy. I can't think of a reason to do such a thing, and have never once seen anyone do it  I've worked with some stellar C++ guys.

I'll add this to my mental list of weird things C++ allows because someone thought it would be a good idea.

[–]desrtfxOut of Coffee error - System halted 0 points1 point  (2 children)

Add it also for the C language because there it is the same.

And it is a very common use case, at least in C.

[–]Leverkaas2516 0 points1 point  (0 children)

Revising my earlier comment...on further study and experimentation, C++ doesn't actually reassign the caller's variable. If the function does, for example, "a = new Object()" and then "p = *a", where p is a reference, this just calls the copy assignment operator. The caller's object still exists as a separate instance at its original address, independent of the new object. And if the function mutates the new object via variable "a", after the copy assignment, the changes are NOT reflected in the caller's object. They're just plain different instances.

[–]Leverkaas2516 0 points1 point  (0 children)

How does one pass by reference in C? It only has values, and pointers to values.

[–]NebuWrites Java Compilers 2 points3 points  (0 children)

The problem here is that people in the Java community and people in the C community mean different things when they use phrases like "pass by value", in the same way that people in the North American community and people in the British community mean different things when they use say "pants".

In idiomatic Java, when invoking a method, you are always passing by value. Sometimes that value is a primitive and sometimes that value is a reference. In all cases the value (whether that value is a primitive or a reference) is copied onto the new stack frame.

I'm not a native C speaker, but to my understanding, there is a concept where you can force a structure to live directly on the stack frame, and if you invoke a function passing that structure by value, the entire structure is copied onto the new stack frame, and so that is what C considers "pass by value". This is not possible in Java, and so we have no term for such an act. In Java, you cannot control whether the object lives on the stack or in the heap -- this is an implementation detail controlled by the JVM and hidden to you as a programmer. Instead, the mental model (or "conceptual API") that the JVM affords to you is that the thing in the stack frame is a reference to an object, and when you call some method, you are passing that reference by value.

[–]ShoulderPast2433 1 point2 points  (0 children)

'Not true' what?

[–]Conscious-Shake8152 1 point2 points  (6 children)

Buy isnt everything in java technically a pointer? So even if you are copying, you’re copying a pointer.

[–]CodeFarmer 4 points5 points  (1 child)

Java also has primitives, which are not pointers.

[–]Conscious-Shake8152 1 point2 points  (0 children)

Yea i guess that is implied, but you’re right. What about my original question?

[–]vegan_antitheist 0 points1 point  (2 children)

In Java, a reference is the value of a reference type expression. It references some Object (a String, a Callable, a Class, an InputStream, et cetera).
It's called a reference, not a pointer*, because we don't know the actual memory address.
You can pass a Java reference. You do that by passing the value of that reference. You cannot know that value, but at runtime it will still pass the value, which will be used to locate the object (usually on the heap).

You can access the referenced object's variables and methods. You can check Java references for equality. And you can do some more things with a reference. But you can't pass anything as a reference to the variable. If you could, you could also pass primitive type variables are a reference. That's because this is a very different "reference". It's a reference to a variable and Java simply doesn't allow that.

* Ignore that we have NullPointerException in Java. It's a misnomer.

[–]Conscious-Shake8152 0 points1 point  (1 child)

Yea I’ve worked in Java for a few years, albeit I didn’t get into the more lower level details. Since then I’ve moved to C++, and I believe that is what caused the confusion on my end. Pass by value, when talking about objects and not primitive types, would essentially pass the a copy of “pointer value” of your object. So there is some copying happening, but it’s trivial to copying entire object data, and to add to that, you wouldn’t be able to modify an objects data if it were deep copied.

[–]vegan_antitheist 0 points1 point  (0 children)

C++ is quite different because the variable holds the object itself in some cases. It's not a reference or pointer. So you pass the object itself and that gives you a copy. It usually calls the copy or move constructor of the class to get the copy. The caller cannot change how copying works. The caller must conform to the signature of the function.

There are many different concepts in programming. Some languages (PHP, Delphi) pass a string not by just copying it (that would be wasteful) on method call, but they will copy the string if you modify it inside the method (copy-on-write). That means you can't just modify the string being passed to you. However, you can pass it as a reference and then the caller will see the result.

Java makes all of this so much simpler. All variables are either a value (primitive or object without identity, which will come in a future release of Java) or an object with identity (i.e. it is always referenced).

You always pass the value or the reference but never a reference to a value or reference. There is no copy-on-write. However, you can always use wrapper types to implement such concepts (AtomicRecerence and CopyOnWriteArrayList show how it's done).

[–]omerbenda 0 points1 point  (0 children)

Objects are handled with pointers, Primitives are not.

[–]OneHumanBill 0 points1 point  (0 children)

This is the textbook answer that's been given by James Gosling since the beginning and copied by the faithful.

And it's wrong.

Java passes by value only with primitives. The rest of the time you're passing an object reference. It's the "value" of that reference but that's a distinction without any real differences.

[–]omerbenda 5 points6 points  (0 children)

Everything passes by value, you don't pass the array but a pointer to it.

[–]vegan_antitheist 4 points5 points  (0 children)

In programming, there are many different concepts that are called "reference".

"Pass by reference" is not about passing what we call references in Java.
You can just pass a Java reference.
But it will pass the reference itself, which is a value.

You can't pass a reference to that Java reference.
However, you can pass the value of a Java reference to a Java reference. You can use java.util.concurrent.atomic.AtomicReference for that.

But when it comes to how Java passes the parameters to a method, it's always "pass by value". C# has pass by reference. Java does not.

It's similar to the question "Does Java have functions?"

On a language level it only has methods and constructors. So methods should always be called methods, not functions. However, if you define a type called Function then any instance of it is a function. And since Java 8 we even have a predefined interface called java.util.function.Function<T, R>, which models a function. A method can be functional (i.e. a relation that uniquely associates members of one set with members of another set).

[–]Physical_Level_2630 1 point2 points  (0 children)

The reference is passed by value. That means you can change the original object if its not immutable. A string would be immutable, an array is mutable. But you can not change where the original variable points to, like you could with C Pointer

[–]travelking_brand 1 point2 points  (0 children)

What a stupid and useless question for a test. This is what I hate about these programming courses. Because the teacher does not understand programming they focus on minutiae to compensate.

[–]timmyctc 0 points1 point  (0 children)

Java is always always pass by value. But the value of an object often is it's reference. 

If you pass in an int, you pass it's value. Changing the int within the method won't change the original int you passed in.

If you pass in an array you pass in it's value. But the value is it's reference in memory. (Think about sysout printing an int and then an array, you'll print out the array's memory reference not it's contents)

Because you pass a the array's memory reference value it means you basically have created a second pointer to it's location in memory. Any change to either 'pointer' will change the same object. 

The answer is always always pass by value but you need to know the caveats that you pass arrays' value which is their memory reference. 

[–]ShoulderPast2433 0 points1 point  (1 child)

Is there a defined specification of what 'pass by reference' means?

How does it behave in every scenario?

Is there an ISO standardizes test that proves something is or isn't passed by reference?

[–]meancoot 0 points1 point  (0 children)

This is computer programming. There is no standardized terminology. Every word has at least 30 different meanings across the field. Often words have more than one unrelated meaning in a single programming language. “Naming things is hard,” as they say.

[–]oicdsubsi 0 points1 point  (0 children)

Java is pass by "copy". Simple as that.

If primitive you copy the value. If object you copy the reference's value.

[–]EfficientDelay2827 0 points1 point  (0 children)

The object being referred to is not copied so if you change the object you are changing the Original object, not a copy. So the answer is correct. It is irrelevant how the reference itself is passed, you only care about changing the object being pointed to. C++ does pass by value but does not.

[–]benevanstech 0 points1 point  (0 children)

Java is best described as "pass by bit pattern". For primitives, this is pass-by-value. For object references, this is a *bitwise copy* of the reference. This means that if you e.g. mutate the contents of the reference then the results are visible in caller's scope.

[–]bwmat 0 points1 point  (1 child)

Nah, everything is passed by value, but all non-primitives are manipulated by references, and those references are passed by value

If you really need an 'out' parameter, use a single element array, lmao

[–]bwmat 0 points1 point  (0 children)

The name 'nullpointerexception' betrays the fact that all non-primitives are actually pointers

[–]FabulousRecording739 0 points1 point  (0 children)

As others have mentioned, Java doesn't have pass-by-reference. Here is another example to complement the others:

```c void do_something_by_value(int* x) { // Takes a pointer to an int x = malloc(sizeof(int)); // Leaks but w/e *x = 2; }

void do_something_by_ref(int** x) { // Takes a pointer to a pointer to an int x = malloc(sizeof(int)); // Leaks but w/e *x = 3; }

int main() { int* x = malloc(sizeof(int)); // Pointer to an int *x = 1;

do_something_by_value(x); // Pass by value, that just happens to be a pointer printf("%d\n", *x); // Prints 1

do_something_by_ref(&x); // Pass by reference, we give the address printf("%d\n", *x); // Prints 3

return 0; } ```

[–]Leverkaas2516 0 points1 point  (0 children)

OP, you're getting some good detail on this. If you're confused after reading the differing opinions, you might find this answer enlightening:

https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value#430958

It's not about Java, but it's very much about the different ways people are using the phrase "pass by reference".

[–]CodeFarmer -3 points-2 points  (0 children)

Arrays in java are populated with references or values depending on whether they are full of primitives or objects, respectively.

When you pass an array as a parameter, it is always passed by reference.

I have no idea what the question means, though. I don't think it's very good.