From the code in the question, it sounds like what you're really asking is: "Is there an edge case where I pass an array reference into a method and modify its contents, but that modification doesn't actually happen?"
No, there isn't. Let's extract some of that code and change some names so they aren't misleading:
public static void changeValue(String[] arg) {
arg[0] = "changed";
}
public static void main(String[] args) {
String[] foo = new String[2];
foo[0] = "not changed";
changeValue(foo);
if (foo[0].equals("not changed")) {
System.out.println("not linked");
} else {
System.out.println("linked");
}
System.out.println(foo[0]);
}
changeValue
accepts an array reference (a value that points to an array), and changes the contents of that array. If the code compiles (e.g., all the types and such are correct) and doesn't throw when run (you're not passing null
or a zero-length array into changeValue
), then no, there's no edge case where that won't work.
What's going on in that code?
If we look deeply at what's going on in that code, we can see why the answer is "no." I find pictures can help, so let's throw some ASCII-art at this.
This line:
String[] foo = new String[2];
gives us this in memory:
+----------+
foo(ref 5426)---->| String[] |
+----------+
| 0: null |
| 1: null |
+----------+
We have a variable, foo
, that contains a value. The value is called an object reference because it refers to an object (in this case, an array, so we sometimes call it an array reference). That's just a value that tells the JVM where the object is. I'm showing it as ref 5426
just to show that it's a value like any other value, not something magical; I've picked 5426 completely at random, we never see the actual value, the JVM hides it from us.
Then you do this:
foo[0] = "not changed";
Giving us:
+-------------+
foo(ref 5426)---->| String[] |
+-------------+ +---------------+
| 0: ref 1897 |---->| String |
| 1: null | +---------------+
+-------------+ | "not changed" |
+---------------+
E.g., the first entry in the array contains value which is a reference to a string object.
Then we do this:
changeValue(foo);
That takes the value from foo
and passes that value to changeValue
. changeValue
receives the value in the argument arg
. So now we have this:
+-------------+
foo(ref 5426)--+->| String[] |
| +-------------+ +---------------+
| | 0: ref 1897 |---->| String |
| | 1: null | +---------------+
| +-------------+ | "not changed" |
| +---------------+
arg(ref 5426)--+
Since main
hasn't returned, foo
still exists, and it has the value ref 5426
. That value was copied into arg
, so arg
also has the value ref 5426
. That value tells the JVM where the array is.
Then you do:
arg[0] = "changed";
which gives us:
+-------------+ +---------------+
foo(ref 5426)--+->| String[] | | String |
| +-------------+ +-----------+ +---------------+
| | 0: ref 2785 |---->| String | | "not changed" |
| | 1: null | +-----------+ +---------------+
| +-------------+ | "changed" |
| +-----------+
arg(ref 5426)--+
The first entry in the array no longer points to the old string, you've replaced the value with a new value that points to a new string. (The old string hangs around until the garbage collector gets around to getting rid of it, but we no longer care, we don't have any references to it.)
changeValue
is done, so it returns, and arg
(the argument) goes away.
Since foo
still has the same value (ref 5426
), when you look up the first entry in it, you see the value that was put there by changeValue
.
How does that tell us the answer is "no"?
For there to be an edge case where the above didn't work, there'd have to be one of these things going on:
Passing foo
's value to into changeValue
and receiving it as arg
not working for some reason.
Passing foo
's value to into changeValue
and receiving it as arg
making a copy of the array for some reason.
There being some difference where we got ref 5426
from that matters when we use it to get the array and change it.
There aren't any edge cases where any of those things happen. :-)