Java: Modifying Objects by Method Call [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
I've read a gazillion times that in Java, arguments passed to methods cannot be modified by the methods. Nonetheless, I find I can modify objects I create as opposed to Java Objects. Consider the following code:
// My Integer Object
class MyInteger {
Integer val;
}
// Change Java Object
public void test1() {
Integer intval; // Integer object
intval = 123;
setInteger( intval ); // THIS DOESN'T WORK
TTY.putR( "Integer Object="+intval);
}
// Change My Object
public void test2() {
MyInteger myInt; // MyInteger object
myInt = new MyInteger();
myInt.val = 456;
setMyInteger( myInt ); // THIS WORKS!
TTY.putR( "MyIntegerObject=" + myInt.val );
}
// Set an Integer object
public void setInteger( Integer val) {
val = 888;
}
// Set a MyInteger object
public void setMyInteger( MyInteger myint) {
myint.val = 999;
}
test1 doesn't work as I have been warned. But test2 works just fine. AFAIK, both are objects and are passed by reference. So how come one works and the other doesn't? (Note: TTY is my print function)

You have either read things that were wrong, or misunderstood what you've been told.
If you pass 'a' to a java method, you cannot have the method change 'a' to be something other than 'a'. However, you can modify 'a'.
In other words, you cannot create an object of the same class as 'a' and return that in place of 'a'. The only way you can return an object created by the method is either to have a place to put a reference to that new object within an object passed to the method, or to return it as the return value from the method.

The best way I've seen this explained:
You pass an object A pointing to a memory address P.
A ===> P
When you modify A by doing A.foo = bar, A is still pointing to P, so the object at P has its property foo changed. However, let's say you want to completely reassign A, and so do A = new MyCoolObject(). This means
P_New <=== A ==/=> P
So when you modify A by doing A.foo = bar, A is no longer pointing to P, so the object at P_New has its property foo changed, but the object at P remains unchanged. This means when you exit the method and go back to whatever parent called the method, A will be completely unchanged.
Disclaimer: I saw this on another Stack Overflow article probably 5 years ago, and am too lazy to find it. If you're reading this right now and you're the person who wrote this, thanks, and forgive my casual plagiarism.

I think you are confused by pass-by-reference vs. pass-by-value. Read this to help clear it up.
You might also have misinterpreted what you've read. A mutable Object can be mutated anywhere -- where it is created or by a method it is passed to.
Good luck.

Because MyInteger the val is a public variable. So ANYONE can modify it.
// Change MyInteger object
public void setMyInteger( MyInteger val) {
val.val = 999; // ACCESING TO A PUBLIC VAR and SETTING IT
}
// Change an Integer object
public void setInteger( Integer val) {
val = 888; // Accesing to the value of the Variable and not modifing it
}

Java is a pass by value language. When you invoke any method with argument it creates new variable and you are changing this variable.
You can look at this also,
Is Java "pass-by-reference" or "pass-by-value"?

Related

Java pass by value query [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
Since java is pass by value.In below code we are passing a value to appendStringMethod not a reference, then why in main method we get HelloWorld not just Hello after calling appendStringMethod() in main.
public class test {
public static void main(String args[]) {
StringBuilder str = new StringBuilder("Hello");
appendStringMethod(str);
System.out.println(str);
}
static void appendStringMethod(StringBuilder s) {
s.append("World");
}
}
However in below code, values are not swapped.
public class Mock {
public static void main(String args[]) {
StringBuilder str1 = new StringBuilder("Hello");
StringBuilder str2 = new StringBuilder("World");
swap(str1, str2);
System.out.println(str1);
System.out.println(str2);
}
static void swap(StringBuilder s1, StringBuilder s2) {
StringBuilder s= s1;
s1=s2;
s2=s1;
}
}
It's because the reference to the StringBuilder is passed by value. You can add characters and they will be in the instance after the method returns. This in the end acts like a pass by reference. It works similarly with the Collection classes (List, Map,...), as well as your own classes.
In the case of primitive types (int,...), Java behaviour is simple: The value is copied in another instance of the primitive type.
In case of Objects, this is the same: Object variables are pointers that holds the Object’s address so the references are copied. The only exception I can think of are String Objects as the characters are stored in an array declared final so that it cannot be modified.
While Java is technically pass by value for everything, as spoken about here, It's best not to think of it like that.
When passing an instance of a class into a method, you're really passing the reference of the object by value.
StringBuilder str = new StringBuilder("Hello");
appendStringMethod(str);
In this code, you are passing a reference to the StringBuilder instance into the appendStringMethod by value.
As a result, str will become "HelloWorld" once the method has been called.
Note: This doesn't apply to primitives such as int and char. Since they are not actual objects, they won't have a reference. This means they will be passed by value in the "expected" way.
In java we pass by value of reference. Have a look at a following example:
public void foo(Integer i) {
i = new Integer(1000);
}
public void bar(Integer i) {
i++;
}
Integer n = new Integer(2000);
foo(n);
bar(n);
System.out.println(n.toString());
I believe that much of the confusion on this issue has to do with the
fact that different people have different definitions of the term
"reference". People coming from a C++ background assume that
"reference" must mean what it meant in C++, people from a C background
assume "reference" must be the same as "pointer" in their language,
and so on. Whether it's correct to say that Java passes by reference
really depends on what's meant by "reference".
--first comment

How Does Java handle Object references? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
If you reference an instantiated object in different classes, do changes get updated to the actual object or just the reference ..
public class First {
List<String> numbers;
public First(){
this.numbers.add("one");
this.numbers.add("two");
}
}
public class Second{
First InstanceOfFirst;
public Second(First F){
this.InstanceOfFirst = F;
}
public void printList(){
for(String s : this.InstanceOfFirst.numbers){
System.out.print(i+", ");
}
}
}
public class Third {
First Reference;
public Third(First F){
this.Reference = F;
}
public void Update(){
this.Reference.numbers.add("three");
}
}
So let's say my main looks likes this:
public static main(String args[]){
First F = new Frist();
Second sec = new Second(F);
Third th = new Third(F);
th.Update();
sec.printList();
}
Would I get one, two or one, two, three as a result.
I guess what I'm trying to ask is: Deos Java make different copies of objects when referenced like this or do they point to the same object??
Please excuse me if my question seems vague ..
The reference points to the object on the heap.
If the object is mutable, and you change its state, then every reference to that object sees the change.
Java doesn't clone or copy anything for you. If you truly want your object to have its own copy, you have to create it.
It's only a problem with mutable classes. Immutable ones, like String, don't suffer from this.
public class Person {
private String name;
private Date birthDate;
public Person(String name, Date birthDate) {
this.name = name; // no need to clone; String is immutable
this.birthDate = new Date(birthDate.getTime()); // need to clone, since Date is mutable.
}
}
Java always uses Pass by value whether its a object reference or primitive or literals.
In your case you are passing the reference of First class object and now you are assigning it to someone else that will also point to the same object in the memory(heap) as shown in below snapshot and by reference it can update the state of the object inside the called method as well.
You have a reference pointing to the same object, so it would result with one, two, three. By passing your instances this way, you can implement a basic singleton pattern (by having a main class hold those instances).
Java is pass-by-value, but with Objects it passes the value of the reference of that object.

How are these two situation different? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
public void otherMethod(){
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("abc");
list.add("abc");
someOtherMethod(list);
System.out.println(list.size());
}
public void someOtherMethod(List<String> list){
list.add("abc");
}
Invoking otherMethod prints 4.
where as
public void otherMethod(){
int a = 10
someOtherMethod(a);
System.out.println(a);
}
public void someOtherMethod(int a){
a = 11;
}
prints 10;
How are the two different. Aren't both local variables? Does sending list reference work in a different way? Please help me understand how the two scenario differ?
Before downvoting please make me understand why this below one also prints 10?
public void otherMethod(){
Long a = new Long(10);
someOtherMethod(a);
System.out.println(a);
}
public void someOtherMethod(Long a){
a = 11;
//or a= new Long(11);
}
In fact conceptually they are not different, in both cases a copy of the original value is passed in as an argument to the method. The thing is that in the first case you have a complex/composite structure of some sort so you pass in a reference copy which is different from the original reference but which still points to the original structure/object.
In the second case you pass in a copy of an int and so the method just operates on the copied int. Unlike that in the first case the method operates directly on the original structure through that copy of the reference (which it receiver from the caller).
Now, in the case of Integer and Long, you work on the original objects through a copied reference. The thing is that you cannot do much on the original object as these classes are immutable e.g. they don't have methods Integer.increment(int n) or Long.increment(long n) which change the original objects by incrementing their values. It would be same if we talk about String (which is immutable) but not the same if we talk about StringBuilder (as the latter is mutable).
public void someOtherMethod(Long a){
a = 11;
//or a= new Long(11);
}
In this example you direct the copied reference to a new object (11)
but the caller still has the original reference which still points
to the same old object (10). You have no way of changing the original
object (from within the called method) just because Long is immutable.
If it wasn't, you would be able e.g. to increment it e.g. by calling
a.increment(1). If that was possible, this is different: you're not
directing the copied reference to a new object, you're using it to call
a method on the original object.
Remember, Java is pass-by-value (always) but certain
differences like these make people confused sometimes.
int are not Objects in Java, so no a is not a reference.

Object Reference passing in Java. Pass by reference working differently in different case?

While playing in Java. I saw different behaviour if an object is modified and given a value and different value if it is assigned a new object. Here is code that I made to show the result.
public class Test {
int i;
public Test(int j) {
this.i = j;
}
public static void main(String[] args) {
Test A = new Test(5);
Test N = new Test(5);
add(A);
makeNew(N);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
}
private static void add(Test t) {
t.i+= 3;
System.out.println("Inside method add() t.i= "+t.i);
}
private static void makeNew(Test t) {
t = new Test(8);
System.out.println("Inside method makeNew() t.i= "+t.i);
}
}
Here is the output of the above code.
Inside method add() t.i= 8
Inside method makeNew() t.i= 8
Value of A.i= 8
Value of N.i= 5
In above example object A is modified to value 8. And object B is given a new object itself. But calling them back only object A shows new value. Object B shows the old value itself. Should not they be showing same value because both case are pass by refernce? I was expecting same value for A.i and N.i.
Here's what happens:
Test A = new Test(5);
Test N = new Test(5);
add(A); // method is add(Test t)
makeNew(N)// method is makeNew(Test t)
t = new Test(8);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
Whenever you make a variable equal to an object and later use new on that object somewhere else like through another reference, your variable you set to the objects reference no longer points to whatever the new object is, but still holds onto the old. So if multiple variables at different scopes hold a reference, they all need a way to have them made equal to whatever the new object is or they no longer are in synch.
I think this will make you doubt clear:
You see N still point to the first object
In your makeNew, you're overwriting the reference to the existing object (that's passed in as the paramter) with your new test(8) object. However, that's local inside makeNew, so the original object sitting inside main(...) is not affected.
Java is pass-by-value. You pass the reference of an object as a value, and you can thus modify that object. However, you cannot modify the actual reference of an object and make it point to something else.
Your question has already been answered here: Is Java "pass-by-reference" or "pass-by-value"?
In Java you do not pass the actual object nor do you pass the reference to the object. You pass copy of the reference to that object. Now when you say
makeNew(N);
N which is the reference to new Test(5) is not passed but the copy of it's reference is passed. In the makeNew() function this copy points to some new object and print the value appropriately but the N will still point to the original object.

Java Object Reference and Java Methods

I am unable to understand how this works
public void addToRule(Rule r) {
if (!getRuleList().contains(r)) {
getRuleList().addElement(r);
}
}
If I run this code:
obj.addToRule(r);
System.out.println(getRuleList().contains(r));
it prints out true how can this happen?
btw ruleList is a vector member of the main class and is not a static variable(don't think this matters but sharing anyway).
import java.util.Vector;
public class RuleEngine{
private Vector ruleList = new Vector();
public Vector getRuleList(){
return ruleList;
}
public void addToRule(Rule r){
if(!getRuleList().contains(r))
getRuleList().addElement(r);
}
public static void main(String args[]){
RuleEngine re = new RuleEngine();
Rule r = new Rule("Rule1");
re.addToRule(r);
System.out.println(re.getRuleList().contains(r));
}
}
class Rule{
public String name = "";
public Rule(String nam){
this.name=nam;
}
}
OK people have told me that this works because of the pass by reference in java. I get it. but what can i do to get a copy of that object instead of its reference?
I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().
For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.
These assumptions are of course without seeing your full code.
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Hope I could help,
Ferdi265
From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.
Consider
class Test {
private List list = new ArrayList();
public List getList() {
return list;
}
}
The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like
Test test = new Test();
String s = "ABC";
test.getList().add(s);
System.out.println(test.getList().contains(s));
Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.
Consider this, however.
Test test1 = new Test();
Test test2 = new Test();
String s = "ABC";
test1.add(s);
System.out.println(test2.getList().contains(s));
This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.
It should always print true, because you add the rule to the rule list in case it is not there. What happens is:
you tell the object to add add a rule to its rule list
the objects checks if the rule exists, and if it doesn't, adds it
So it is guaranteed to contain the rule after the code is executed.

Categories