0

I am quite confused with how Object works in Java since I run into this problem.

Let's say I have a function called checkDateValue (code looks like this)

private boolean checkDateValue(Date d1, String msg) {
    if (d1 == null) {
        msg = "d1 is null!";
        return false;
    }
    return true;
}

Here is the place I call this function:

String msg = null;
Date d1 = null;
if (!checkDateValue(d1, msg)) {
    system.println(msg); //msg is still null..... 
                         //what I need is the message generated in the function
}

As far as I know, if I put a customized Object (e.g.

myObj { private String msg;} 

) into a function, and we change the value of msg inside the function, when we get out of the function, the change of msg is kept. However, I think String is also considered as an Object in java. Why the change is not kept?

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
user2296188
  • 139
  • 8
  • possible duplicate of [Passing a String by Reference in Java?](http://stackoverflow.com/questions/1270760/passing-a-string-by-reference-in-java) –  Apr 30 '13 at 18:47
  • @delnan: I think you are right.. I have the same question as in that post..... – user2296188 Apr 30 '13 at 18:57
  • Thanks you for all you guys' help~!!! I think I got a clear idea now. I admit my keyword search skill is pretty bad...... – user2296188 Apr 30 '13 at 19:03

6 Answers6

2

Java doesn't have "out" function arguments; they are copies of references. Even though you change msg in the function, it does not affect the caller's variable.

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
1

String is special, is immutable and is diffrent from normal Object. Java's String is designed to be in between a primitive and a class.

String is passed by value, but unfortunately every change on String make new value, so your old reference has old value.

I think this is good explanation: https://stackoverflow.com/a/1270782/516167

Community
  • 1
  • 1
MariuszS
  • 30,646
  • 12
  • 114
  • 155
  • 4
    Anyone can create an immutable class. String is special in some regards (e.g. there are literals), but not in this case. It's just another immutable class, and a reference type like every other class. And as I said before, mutability has no effect on what OP describes. –  Apr 30 '13 at 18:50
0

msg = "d1 is null!"; and msg=null are two different String objects. Strings are immutable in Java.The reference is passed by value, i.e., a copy of the reference is passed. and since a String is immutable object , the assignment inside the method creates a new String object that the copy of the reference now points to. The original reference still points to the null String. Your method call is same as :

Object obj = null; // obj points to nowhere
foo(obj); // passed the reference values to method argument
void foo(Object o)
{
   o = new Object( );  // o points to new Object, but obj still points to nowhere
}
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • 4
    Mutability has nothing to do with it. –  Apr 30 '13 at 18:47
  • 2
    @delnan - If `String` were mutable, then OP could pass in an empty string (instead of `null`) and have the method fill in a non-empty value as appropriate. – Ted Hopp Apr 30 '13 at 18:55
  • 1
    @delnan - Really? Can you think of any consequences if it were mutable ? – AllTooSir Apr 30 '13 at 18:56
  • 2
    Yes, *of course* then one could mutate the object, but assignment works the same either way. It's my knee-jerk reaction because I keep seeing people explaining "you see, immutable objects work differently ..." and the original answer read a lot like that. –  Apr 30 '13 at 19:00
  • 1
    To be more specific, if inside the method the code was something of this sort `msg += "d1 is null!";` and if `String` were indeed mutable, then do you think Op would have got the o/p what he is getting in this case ! – AllTooSir Apr 30 '13 at 19:05
  • The way `+=` is currently defined, no it wouldn't, it would just be `msg = msg + "d1 is null";` ;-) An overloaded (yeah, not happening) `operator+=` or a mutating method would work though. And my point was exactly that - you'd need to perform a different operation, as assignment can never do what OP expects, regardless of mutability. –  Apr 30 '13 at 19:09
  • *"you see, immutable objects work differently ..."* , No you misinterpreted the answers , since `msg = "d1 is null!";` creates a new String object in this case , it was relevant to mention it while answering. If it were a `StringBuilder` object and you would have done `append()` to it , then both the references outside the method and method parameter would have been refering to the same object!!! – AllTooSir Apr 30 '13 at 19:09
0

In Java, you cannot pass back a value to calling code by assigning to a method parameter. You are right that you can alter the internal structure of any parameter and that change will be seen in the calling code. However, assigning to a parameter is not the same thing as altering the internal structure. Also, a String is immutable—once created, its internal structure cannot be altered.

A common trick to do what you what is to use an array argument:

private boolean checkDateValue(Date d1, String[] msg) {
    if (d1 == null) {
        msg[0] = "d1 is null!";
        return false;
    }
    return true;
}

Then call it like this:

String[] msg = new String[1];
Date d1 = null;
if (!checkDateValue(d1, msg)) {
    system.println(msg[0]);
}
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 2
    By "trick" you mean ugly hack that you should avoid like the plague. – Tom Hawtin - tackline Apr 30 '13 at 18:58
  • @TomHawtin-tackline - Not really. That "trick" is used in the core Java libraries. What's plague-like about it? – Ted Hopp Apr 30 '13 at 19:04
  • There's a difference between passing an array to retrieve a number of values, and passing a singleton array just to emulate pass-by-reference. –  Apr 30 '13 at 19:06
  • @delnan - Um, what's the difference? (And by "singleton array" I assume you mean an array of length 1, not an array that is a [singleton](http://en.wikipedia.org/wiki/Singleton_pattern).) – Ted Hopp Apr 30 '13 at 19:32
  • One is the established pattern used in a number of libraries (Java and otherwise) and is perfectly natural, the other is a ugly hack (both implementation-wise and w.r.t the interface) to semantics that are usually neither useful not desirable. Or less literally, I'm saying you can't cite those uses of arrays-as-parameters to defend this "trick", as they use them for very different purposes. (And yes, I'm using singleton in the mathematical sense, i.e. containing a single element.) –  Apr 30 '13 at 20:04
  • @TedHopp The Java library is full of shocking code. I don't think it does it that often either, particular not in deliberately public APIs. It's a dirty hack. – Tom Hawtin - tackline Apr 30 '13 at 20:05
0

This is related to the fact that

Java passes objects as references passed by value.

You can't change the reference argument to point to something else. You can change the object state.

You can read more here

Community
  • 1
  • 1
BobTheBuilder
  • 18,858
  • 6
  • 40
  • 61
0
if (!checkDateValue(d1, msg)) 

{
    system.println(msg); 
} 

when you call checkDateValue method a reference String msg = null; Date d1 = null; to the method is passed which is pass by value. When method gets executed then msg variable in checkDateValue will get referenced to "d1 is null!" Here, msg variable in call remains same

DanielBarbarian
  • 5,093
  • 12
  • 35
  • 44
Akshay Gaikwad
  • 420
  • 6
  • 13