4

I am learning about References and Datatypes in Java and this particular code is still confusing me. I understand that all of the primitive types in Java are value types (byte, short, int, long, float, double, boolean, char), and when you're using a string or an object it's a reference type. When I was taught to declare and initialize a variable, I was told to think of it like creating a box. So if I create a variable "y" and give it a value of "5" it's like I've created a box called "y" that contained the value of 5. My teacher said that if I then try to call y in a method (check out the code below for more detail) the value will remain untouched because it's a primitive datatype so I'm only passing in 5, not the variable that CONTAINS 5. Well I'm confused because if I'm passing in the value of 5, why wouldn't the following method add one onto it.

public class ReferenceAndValueTypes {
    public static void main(String[] args) {

        int y = 5;
        addOneTo(y);

        System.out.println(y);

    }


    static void addOneTo(int number){
        number = number + 1;
    }
}

The output is 5 and that confuses me greatly. The teacher says it's because int is a value type so we're not passing the y variable in, and we're not operating on that variable but rather the value of that variable. However, the value of that variable is 5 and since the method adds one, shouldn't it be 6? Or, is it because y is a value type, the method cannot work with it so it just has to print out the initial value of y which was 5?

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 2
    You're operating on a **copy** of that variable. – Oliver Charlesworth May 12 '15 at 07:40
  • 1
    the value is 6. but only in the addOneTo method. (try to print out the number variable in your addOneTo method) ... you are passing the value "5" to your add-method. you add 1 to it --> gives "6". BUT from where you have called it .. the value hasn't changed (how should it ... you just passed the VALUE to your method) – griFlo May 12 '15 at 07:41
  • 3
    @Seelenvirtuose I'm not sure that's a reasonable dupe here, since the OP doesn't understand the difference between pass-by-value and pass-by-reference. – Patrick Collins May 12 '15 at 07:47
  • 1
    Thank you all for that explanation it makes much more sense now! –  May 12 '15 at 07:48
  • @PatrickCollins Sure, it's hard to find those questions that potentially could answer yours if not even knowing the words to search for. But that does not qualify this question as a new question on its own. The possible "duplicate" has still everything that Carson Clark needs to know for an answer. At least, I agree (a little) with you, which is the reason why I did not downvote. – Seelenvirtuose May 12 '15 at 07:51
  • @PatrickCollins As far as I understood SO, it is meant as FAQ for programming/developping related issues. And we obviously have already a good question with a good answer about this topic. This question simply does not add any value. Sorry, but this is a reason to close. But I am willing to accept that the OP needs help and gets it here (even in a form of a duplicate link - which by the way also teaches some useful concepts). – Seelenvirtuose May 12 '15 at 07:53
  • https://www.youtube.com/watch?v=TWFIKR3Yn0o – Jean-François Corbett May 12 '15 at 08:16

5 Answers5

3

Java primitives (int, long, boolean, etc) are not references, they're actual values. When you have addOneTo(y);, addOneTo receives a copy of the value. That copied value is incremented by one, and then lost when the method exits.

As an analogy, when you see a primitive method parameter you can think of it as a photocopier. In contrast, an object reference is the same as passing a notepad with something written on it. The method will see the same object, not a copy of it, and so changes made to it will be present after the method exits.

Changing the name of the parameter can make this a little clearer

static void addOneTo(int numberA) {  // numberA is not the same as the int in the calling method, it's just an exact copy of it
    numberA = numberA + 1; // numberA is now incremented by one
    // method exits, numberA is lost
}

If you want to have a method that provides increment functionality, you can define one that returns the result.

public static void main(String[] args) {
    int x = 3;
    addOneTo(x); // x is still 3
    x = addOneTo(x); x is now 4
}

static int addOneTo(int number) {
    return number + 1;
}
Steve Chaloner
  • 8,162
  • 1
  • 22
  • 38
  • if you want the change variable back, you can change that method to have an int as return type, and return it. maybe provide an example for this as well? – Dude May 12 '15 at 07:48
  • Before you run off and test that analogy with String objects, make sure you understand about immutable instances. – Steve Chaloner May 12 '15 at 07:49
  • So If I wanted to return the value from the method I would just need to include the Sys.out.print(y); so when the method is called it would also print out the value of y and it wouldn't be lost? –  May 12 '15 at 07:50
  • See edited version. Calling System.out.println(y) would just write the value to wherever your standard output appears - you wouldn't be able to do anything with it. – Steve Chaloner May 12 '15 at 07:53
  • 1
    The object/primitive distinction is misleading here. Even if we were talking about an object type, the observed behaviour would be the same in this case. – Oliver Charlesworth May 12 '15 at 08:02
  • Indeed, a larger set of examples would be needed to fully flesh out the differences in behaviour - especially in the case of assignment. For other operations, it depends - if the method was e.g. adding something to a List, the change would be visible later; if it was calling replace on String, it wouldn't. – Steve Chaloner May 12 '15 at 08:08
  • Of cource, a single example would be needed for assignment, and it's already given...and shown not to work. – Steve Chaloner May 12 '15 at 08:08
0

Because primitive types in Java are passed by value, not reference. Inside addOne() i is treated as local variable that is copied from passed argument, so any changes in it don't change the variable that is passed by caller.


P.S. This also works for objects indeed. For example, this code snippet:

void changeString(String s) {
    s = new String("new");
}

String s = "old";
changeString(s);
System.out.println(s);  

prints "old", because in changeString(), s reference is copied, thus changing it inside method (assigning new reference) has no effect to caller's s variable.

Alex Salauyou
  • 14,185
  • 5
  • 45
  • 67
-1

As simple as it is, java is written as pass-by-value. If you increment the number in your addOneTo method then you are changing the value of the reference of your parameter number. by this the number does not refer to your original y variable anymore and hence does increment it. This doesn´t work on any primitive typ.

Community
  • 1
  • 1
SomeJavaGuy
  • 7,307
  • 2
  • 21
  • 33
-1

If a variable x holds a reference type, then it points to an object. If it holds a value type, then it points to the value. When you call some function f(x), the thing that is passed to f is the thing that x points to, not x itself.

So here, if you said something like

int y[] = new int[1]{5}

and then said

number[0] = number[0] + 1;

inside of addOneTo, then the value of y would be modified outside --- the thing that addOneTo is acting on is the array containing that number.

On the other hand, when int y = 5, then the thing you're acting on is the number. You're making a new name that points to the same value (5), and when you say

number = number + 1;

what you really mean is:

number2 = number + 1;
number = number2;

and then you throw away the result.

Patrick Collins
  • 10,306
  • 5
  • 30
  • 69
  • 1
    It doesn't point to the value, it *is* the value (or maybe *has* the value). – Oliver Charlesworth May 12 '15 at 07:47
  • @OliverCharlesworth I think that saying "variables point" in general is a fair statement --- they refer to memory addresses, which contain values. `y = 5` means "the memory address referenced by 5 contains the value 5", where as `y = new int[1]{5}` means "the memory address referenced by 5 contains an array of length 1." I don't think that saying "sometimes variables are values, sometimes variables are something else" makes it clear to a beginner what's going on. – Patrick Collins May 12 '15 at 07:50
  • There is a fundamental difference between primitive types and object types, though. A Java beginner will not get very far if they don't understand that difference. – Oliver Charlesworth May 12 '15 at 07:57
  • @OliverCharlesworth Having learned programming in C first, I find it most natural to say "every variable is a name for a memory address; sometimes you make the name refer to a different memory address, other times you change the thing at the memory address" to be the most natural way of thinking. Yes, the JVM abstracts this away from you, but I think the fundamental idea is the same. YMMV. – Patrick Collins May 12 '15 at 07:59
-1

Your question has answer

int is a basic data type and they are passed by value and not by references so the value remain unchanged :)

amith
  • 399
  • 1
  • 2
  • 11