11

In a class, I have:

private Foo bar;
public Constructor(Foo bar)
{
    this.bar = bar;
}

Instead of creating a copy of bar from the object provided in the parameter, is it possible to include a pointer to bar in the constructor such that changing the original bar changes the field in this object?

Another way of putting it:

int x = 7;
int y = x;
x = 9;
System.out.print(y); //Prints 7.

It is possible to set it up so that printing y prints 9 instead of 7?

leonbloy
  • 73,180
  • 20
  • 142
  • 190
Matthew Piziak
  • 3,430
  • 4
  • 35
  • 49

5 Answers5

17

When a variable is used as argument to a method, it's content is always copied. (Java has only call-by-value.) What's important to understand here, is that you can only refer to objects through references. So what actually happens when you pass a variable referring to an object, is that you pass the reference to the object (by value!).

Someone may tell you "primitives are passed by value" and "non primitives are passed by reference", but that is merely because a variable can never contain an object to begin with, only a reference to an object. When this someone understands this, he will agree that even variables referring to objects are passed by value.

From Is Java "pass-by-reference" or "pass-by-value"?

Java is always pass-by-value. The difficult thing can be to understand that Java passes objects as references passed by value.

From http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.

In Java, there is no counter part to the C++ "reference type" for primitives.

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 2
    The first sentence is right, but might be misleading for many people who come to Java thinking that a "variable is an object" (when actually a variable is a reference to an object -or a primitive). What a beginner must first understand is that the object itself is never copied when passed as argument. – leonbloy May 05 '10 at 20:08
8

Your last example works that way because int is a primitive, it is copied by value. In the first example, "this.bar" would hold a copy of the reference (sort of pointer) to bar. So if you change the original bar (internally), the change will be reflected in your class. Try it.

leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • 1
    "int is a primitive, it is copied by value" may be slightly confusing. References are also copied by value. – aioobe May 05 '10 at 19:34
  • 2
    Yes. But the poster was thinking in term of objects. It is important to understand -to begin with- that objects (contrarily to C++) are NEVER copied by value. – leonbloy May 05 '10 at 20:13
4

To get that behavior you could modify a member of an object:

public class Number{
  int value;
  Number(int value){
    this.value = value;
  }
  public String toString() {
    return "" + value;
  }
}

You could then do:

Number x = new Number(7);
Number y = x;
x.value = 9;
System.out.println(y);//prints 9
Adam
  • 43,763
  • 16
  • 104
  • 144
2

Java never copies objects. It's easiest to think of in terms of for each "new" you will have one object instance--never more.

People get REALLY CONFUSING when they discuss this in terms of pass by reference/pass by value, if you aren't amazingly familiar with what these terms mean, I suggest you ignore them and just remember that Java never copies objects.

So java works exactly the way you wanted your first example to work, and this is a core part of OO Design--the fact that once you've instantiated an object, it's the same object for everyone using it.

Dealing with primitives and references is a little different--since they aren't objects they are always copied--but the net effect is that java is just about always doing what you want it to do without extra syntax or confusing options.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • Well, I'm reading this, memory object models aren't a thing I consider hard. And here I am, because Java just isn't doing what I intended to do, I would agree with you if you argue that it is entirely my inability to write Java. But the fact of the matter is, Java is not always doing just about what you want to do, that statement is false and misleading. Knowing a language model in and out is an invaluable knowledge and you should not be discrediting that knowledge with any super feature of Java or any other language for that matter. – Pedro Rodrigues Dec 12 '18 at 14:14
  • @PedroRodrigues Okay, if you understand memory models and pointers I can help you a little more--here is the easiest way to understand it: 1) The thing you pass to a method can't be changed by the called code 2) In the case of intrinsics the value won't change. 3) In the case of objects, the object pointer won't change. If what you intended to do was alter a passed pointer (change the originating pointer) then just forget about that with java, it adds a lot of complexity to the code with no serious benefit. Otherwise I'd love to hear what you wanted to do where java did it differently. – Bill K Dec 12 '18 at 17:05
0

In order to keep the original value of member bar, you will need to implement Cloneable interface. Then before assigning a new value to the object, you will need to make a clone of it and pass the cloned value and assign new values to the cloned object. Here is a tutorial on how to do it http://www.java-tips.org/java-se-tips/java.lang/how-to-implement-cloneable-interface.html .

CoolBeans
  • 20,654
  • 10
  • 86
  • 101