5

Here a beginners question.

Is there any difference in JAVA between passing an object as argument to a method or returning that object from the method. For instance: Is it better to pass a List as an argument and fill it in the method or just allow the method to return a list?

My guess is that it should be no difference since a reference is returned and nothing is copied. But is there something more subtle behind?

thanks in advance

Altober

Altober
  • 956
  • 2
  • 14
  • 28
  • In programming each module/method should be as selfish as possible. Only pass the minimum. If the list is needed in another method, set it as a global field and change it in the method. Otherwise pass the list as a parameter. – Peter_James Nov 21 '13 at 10:40
  • Java does not pass by reference, Java does ALWAYS pass by value! – user1567896 Nov 21 '13 at 10:40
  • 1
    Nonsense, @user1567896, class instances are passed by reference (by passing the reference by value). Hence almost the opposite of what you said (and what many believe) is true. – Ingo Nov 21 '13 at 10:42
  • 2
    Nonsense, @Ingo: Java passes objects as references and this reference is passed by value. (as youself stated) – user1567896 Nov 21 '13 at 10:43
  • @user1567896 So we can also say that FORTRAN passes **always** by value, since it passes the address of variables by value? Then there is simply no such thing as passing by reference in this world. – Ingo Nov 21 '13 at 10:47
  • This conversation is only going to confuse more people who dont know if its pass by value or reference – Ankit Rustagi Nov 21 '13 at 10:47
  • 1
    @Ingo Java is strictly pass by value. In the case of primitives, a copy of the value is passed. In the case of objects, a copy of the reference is passed. – JamesB Nov 21 '13 at 10:48
  • 3
    @Ingo: C++ can pass by reference. You can pass a local variable to a method, and have this method assign a new value to its argument, and have the local variable in the calling method be assigned. That's what pass by reference is. – JB Nizet Nov 21 '13 at 10:49
  • @Ingo: see comment from JB Nizet – user1567896 Nov 21 '13 at 10:50
  • @JBNizet I know. This is like in Fortran, as I said above. By looking at the machine code you'll see that an address is passed by value. Hence, by the same argumnetation as above, one could (misleadingly) say that Fortran (or C++) always pass by value. But, it is much more honest to say that variables are passed by reference and in Java, objects are passed by reference, as this is exactly what happens. – Ingo Nov 21 '13 at 10:55
  • @Ingo: Sorry, but this is not honest, it is simply wrong! It is not the same if you pass a reference by value or by reference. See this link: http://www.yoda.arachsys.com/java/passing.html (especially chapter 'Why is all this important?'). It can explain it better than I can in this comment. – user1567896 Nov 21 '13 at 11:06
  • The link you point to, @user1567896, does explain it almost right, yet in a confusing language. This confusing language with terms like "passing a reference by value" is exactly what I oppose. I never said that you can pass a reference by reference in Java, which is impossible because only references to objects exist. Instead of "Java always passes by value." a much better slogan would be "In Java, there are only object references." -- Look what confusion appears: suddenly, there appear "copies of references" and nonsense like that. – Ingo Nov 21 '13 at 11:18
  • @Ingo See [this excellent answer](https://stackoverflow.com/a/373429/2074869) for the confusion about pass-by-value/reference. It boils down to whether new storage is used (call-by-value) or not (call-by-reference), no matter what the passed thing actually is. – Wolfson Sep 17 '20 at 14:26

5 Answers5

8

Many of the comments seem to have misunderstood what you mean.

I believe you're asking the difference between

public void myMethod(List list) {
    list.add(new Object());
}

and

public List myMethod() {
    List list = new ArrayList();
    list.add(new Object());
    return list;
}

Correct me if I'm wrong.

There is no rule to say which one is right. It all depends on how you wish to design your program. The latter method won't allow you to use existing Lists, so there may be performance issues to be considered.

You can also perform method chaining when returning values from a method, so sometimes you could take both a parameter and returning a value. A variation from this is a method that will use an existing List if it is passed as a parameter, but create a new List if the parameter is null. However this can be confusing to the caller.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • +1 for limitation, The latter method won't allow you to use existing Lists, so there may be performance issues to be considered. – pramodc84 Sep 29 '17 at 07:05
4

First, there is no "pass by reference" in Java: the language is passing references by value (it is not the same thing).

The answer to your question is "it depends": passing an object as an argument to a method lets you reuse the same object in multiple invocations, while returning an object forces the method to supply a new or an existing object to the caller.

Consider this example: you are collecting data from several methods, and you need to put all the data in one list. You can have methods returning lists with their data

interface DataSource {
    void supplyData(List<Data> list);
}

or you could pass these methods a list, and have them add their data to the same list:

interface DataSource {
    List<Data> supplyData(); 
}

In the first case, you could loop through multiple data sources, passing them the same list:

List<Data> bigList = new ArrayList<Data>();
foreach (DataSource s : mySources) {
    s.supplyData(bigList);
}

In the second case, you would need to get individual lists from the calls of supplyData, and put their content in a big list that you keep in your loop:

List<Data> bigList = new ArrayList<Data>();
foreach (DataSource s : mySources) {
    List<Data> tmp = s.supplyData();
    bigList.addAll(tmp);
}

In the second case each invocation creates a temporary list tmp that gets discarded after its content is added to the big list.

Note that passing an existing list is not necessarily a better solution - in fact, there are situations when you should avoid that.

For example, when you deal with externally supplied plug-ins, you should prefer the second strategy. Otherwise, a malicious implementation of the DataSource interface would be able to manipulate the common list in ways not expected by your program, such as adding its items ahead of everyone else's, removing items that came from other sources, examining items from other sources, and so on.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • "passing something by reference" does mean exactly the same as "passing a reference to something". Therefore .... – Ingo Nov 21 '13 at 10:59
  • @Ingo Nope, it doesn't (although that's a very popular misunderstanding). These are completely different things. "Pass by reference" implies a very specific semantics that is not present in Java. – Sergey Kalinichenko Nov 21 '13 at 11:00
  • Care to point to something that explains the alledged difference between "passing X by reference" and "passing a reference to X"? It is true that you can only create references to objects, not to variables, in Java, and this is a good thing. Nevertheless, once you have a reference, and pass it, the thing that is referenced may be mutated. This is the whole point of the question. – Ingo Nov 21 '13 at 11:08
  • @Ingo Please do not mix the point of the question and the point of your complaint in the comment: you said "passing something by reference" does mean exactly the same as "passing a reference to something", which is wrong, because pass by reference specifically requires creating references to variables ([link](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference)). Java's way of passing object parameters is sometimes called ["call by sharing"](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing), which is *not* the same thing. – Sergey Kalinichenko Nov 21 '13 at 11:18
  • In that Wiki article you link, it is explained very well: "In some cases, the term "call-by-value" is problematic, as the value which is passed is not the value of the variable as understood by the ordinary meaning of value, but an implementation-specific reference to the value. The effect is that what syntactically looks like call-by-value may end up rather behaving like call-by-reference or call-by-sharing, often depending on very subtle aspects of the language semantics." – Ingo Nov 21 '13 at 11:30
  • @Ingo Although this statement is correct in general, passing object references by value in Java never behaves like call-by-reference, only like call-by-sharing. – Sergey Kalinichenko Nov 21 '13 at 11:37
  • The confusions arise here because of an over-complicated terminology. Everybody who knows assembly or machine language knows, of course, that only pass by value is possible: you load something in a register, push it to the stack and that is it. (The alternative of copying objects that are larger than a machine word to the stack has long been abandoned, for obvious reasons). – Ingo Nov 21 '13 at 11:52
2

In addition to the answer from dasblinkenlight, which is correct (it depends), returning a list from the method also has advantages over passing a list as argument.

By passing a list as argument, the caller has the responsibility to choose the appropriate List implementation, to initialize it to the appropriate size, and to pass a list that is compatible with the algorithm of the called method. Often, the caller doesn't have the knowledge that is necessary to make the good choice.

Whereas if the called method returns a list, it can:

  • return Collections.emptyList() if nothing has to be returned
  • return a well-dimensioned ArrayList
  • return a subList or an unmodifable view or transformed view of a list it already has in memory, instead of making a copy
  • do anything with the list it creates without fearing that the list passed as argument is unmodifiable, or fixed-size, or already contains elements.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

No difference, both are references to list object. Personally I prefer that results are given by return and leave the arguments. But that might force you to create a new list, and that might cost you (performance, memory).

Returning allows for chaining.

pjvleeuwen
  • 4,215
  • 1
  • 18
  • 31
1

As you are probably aware, everything in Java is pass-by-value.

Is there any difference in JAVA between passing an object as argument to a method or returning that object from the method?

No real difference as it is the reference that is being passed around in both cases.

Is it better to pass a List as an argument and fill it in the method or just allow the method to return a list?

Depends on your requirements I guess. Does the method require a list as input or can it construct it entirely by itself?

My guess is that it should be no difference since a reference is returned and nothing is copied?

Strictly speaking, this is not true as a copy of the reference is returned.

Wolfson
  • 1,187
  • 17
  • 22
JamesB
  • 7,774
  • 2
  • 22
  • 21
  • No, objects are not passed by value. They're not passed at all. Only references are passed. Usually, when one passes a reference to something, we say that something is passed by reference. – Ingo Nov 21 '13 at 10:56
  • 1
    @Ingo I don't agree. If it was strictly pass by reference, the original reference would be passed. – JamesB Nov 21 '13 at 10:59
  • What you mean "original reference"? The reference is, in the JVM, just a machine word that holds an address or some value that can easily be mapped to an address (that, in turn, points to the object). Tell me, if I pass 42 to a method, will it be the "original 42"? – Ingo Nov 21 '13 at 11:02
  • Also, your notion of "copy of the reference" does not make any more sense than "copy of 42" – Ingo Nov 21 '13 at 11:03
  • 1
    @Ingo I'm assuming you have downvoted my answer and yet you are the only user on this post who is claiming Java is pass by reference where objects are concerned. – JamesB Nov 21 '13 at 11:03
  • 1
    @Ingo, have you read JamesB's reply? His answer is absolutely correct. Everything in Java is passed by value. Java has only 2 groups of types: value types (primitives) and reference types (objects). In both cases copy of value is passed. – edio Nov 21 '13 at 11:04
  • @JamesB Lets say you have reference `String x = "foo"` and you have method `void change(String x){ x="bar";}` and you will use `change(foo)`. Will it affect `foo`? If not then it means you didn't pass reference to method, but only value of that reference. – Pshemo Nov 21 '13 at 11:08
  • Sorry to say that, but you all seem to confuse a reference to a String object, and a reference to a variable that holds that reference to a String object. The latter does not exist in Java. This is the important point which helps to understand parameter passing, assignment and operators like (==). – Ingo Nov 21 '13 at 11:23
  • @Ingo My definition of pass-by-value: "Pass by value means the called methods' parameter will be a copy of the callers' passed argument. The value will be the same, but the identity - the variable - is different" This is why I have been stressing the word copy in my posts. – JamesB Nov 21 '13 at 11:37
  • What variable, @James? What is "the variable" when you call `meth(3+5)`? Only values (!!!!!!!!) are passed. Variables are not passed at all. (This is probably what most people saying "Java is pass by value" really mean.) – Ingo Nov 21 '13 at 12:19