How Does Java handle Object references? [duplicate] - java

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.

Related

Java: Modifying Objects by Method Call [duplicate]

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"?

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 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.

ArrayList references behavior

I am totally confused with ArrayList behavior. Wrote really long post, then realized no one is going to analyse huge code, so just core of the problem. Numbers are for convenience, but in my app these 0 and 24 are dynamic values.
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
vb3=sortedBlocks.get(0);
vb3.setPacketNumber(24);
Essentially my final aim is to: modify and add back to arrayList as new value. However when I do that the guy at position 0 in ArrayList -> unsortedBlocks.get(0); replicates all the changes done to vb3 which of course is not what I want. I want vb3 acquire same values as VoipBlock inside of ArrayList, but I want it to be detached.
This is yet another case of passing by reference. I hate technical explanations - Java passes everything by value, BUT in some cases it passes references by values - this is same as saying not-oily oil. Please help.
It reminds me my start of learning JavaScript - I hated the language - until I watched proper materials at lynda.com - JavaScript Good Practices? - Diagrams killed me. It is the lazy description that turns us-youth away from brilliant technology, not the technology itself.
Please don't let it bother my stress and don't be in any way offended by me, it is just general complaining, maybe someone will look at it and make life better :-)
Thanks for Your time,
Desperately awaiting for help :-)
To achieve your objective you can use clone method. you have to override this method in VoipBlock class
Lets say VoipBlock is as follows
public class VoipBlock {
private int packetNumber;
private String type;
public int getPacketNumber() {
return packetNumber;
}
public String getType() {
return type;
}
public void setPacketNumber(int value) {
packetNumber = value;
}
public void setType(String value) {
type = value
}
public VoipBlock clone() {
VoipBlock clone = VoipBlock();
clone.setType(this.getType());
clone.setPacketNumber(this.getPacketNumber());
return clone;
}
}
So, using the same code you can do like as follows
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
sortedBlocks.add(vb3);
vb3=sortedBlocks.get(0).clone();
vb3.setPacketNumber(24);
Note that upon calling clone method in above code segment, vb3 get assigned with a new VoipBlock instance. And already inserted VoipBlock to the array remains unchanged.
if you are looking to have kind of sample instances of VoipBlock instances which you later wanted to use in creating similar instances like them. check on immutability/mutability aspect of the code. check "Effective Java" by Joshua Blouch
The following will always copy the reference of b to a:
AnyClass a = ...;
AnyClass b = ...;
a = b;
What you want is probably to clone the object:
a = b.clone();
If I understand correctly, you're a bit unsure about how references and values work. I think the rule of thumb is that primitive types like int, char, boolean and maybe String are copied but Objects just have their reference passed.
The line vb3=sortedBlocks.get(0); completely replaces whatever vb3 used to be with the first thing in the ArrayList. And yes, it won't be a copy, it will be a reference to the same object in memory. So whatever you do will affect both of them. You need to either manually copy over all the information you need or to use a clone() or copy() function.
So for example, in your code, the line VoipBlock vb3 =new VoipBlock(); is a bit redundant because you're overwriting the new instance straight away.
What you really need here is to either use a copy constructor or declare VoipBlock to be Clonable so you can use the clone() method.
What you are interpreting as passing by reference is not actually passing by reference. Java objects are really pointers. Because of this you are passing the value of the pointer. So when you do:
vb3=sortedBlocks.get(0);
you are really assigning vb3 to point to the same locations in memory as sortedBlocks.get(0). Therefore when you manipulate vb3 properties through their setters, the result is seen in both.
If you want two separate pointers you need to use the new keyword or use the clone() method which does this under the hood.
An example to prove this is:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public void doSomething(Person p) {
p = new Person("Bob");
System.out.println(p.getName());
}
public static void main(String[] args) {
Person p = new Person("Billy");
System.out.println(p.getName());
doSomething(p);
System.out.println(p.getName());
}
}
Since Java is pass by value the output will be: Billy, Bob, Billy. If Java were pass by reference it would be Billy, Bob, Bob. If I did not do the new Person in the doSomething() method and instead used the setName() method I would end up with Billy, Bob, Bob also but this is due to the fact I'm now modifying off the same pointer not that I passed by reference as the example above proves that's not the case.

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