I have this code. But I don't know how to explain the result:
ArrayList<String> first = new ArrayList<String>();
first.add("1");
first.add("2");
first.add("3");
ArrayList<String> second = new ArrayList<String>();
second = first;
System.out.println("before modified:"+second.size());
second.clear();
System.out.println("after modified:");
System.out.println(" First:"+first.size());
System.out.println(" Second:"+second.size());
The result will be: 3 / 0 /0
The problem I don't know is: when you assign first = second; so, both first and second array will point to same object (1,2 and 3). after you clear all elements on second array, so all reference between second array and these objects will loose (no problem here).
The thing I don't know is: but these objects (1,2 and 3) still hold reference to first array. Why first array's size is 0.
Please explain for me.
Thanks :)
By assigning second = first, there is only one arraylist with two references. The references are the same. So, when call clear using one of the two references (first or second), clear will be performed on the referenced arraylist.
This is something else than you first thought. It's not so that assigning the second = first all the references of the strings you added to the first one, will be copied into a new ArrayList object, that would be magic (in Java).
When you do first = second your ArrayList items will point to the same memory locations. Doing a .clear will remove the elements to which the ArrayList is pointing to. This will have repercussions on the other ArrayList.
If you just want to copy the elements of ArrayList1 to ArrayList2, you could do something like so: ArrayList<String> second = new ArrayList<String>(first);
but these objects (1,2 and 3) still hold reference to first array.
Why first array's size is 0.
ArrayList<String> second = new ArrayList<String>();
second = first;
is the same as writing
ArrayList<String> second = first;
You have made second reference point to the first arraylist,it is not using a new arraylist. So when you call clear it clears the "first" arraylist created - you have two references pointing to one arraylist.
When you assign one ArrayList to two variable and modify any one of them, this will reflect in both.So operation performed in any of one variable also reflect in second one. (Single object referenced by two variable).
In Java a variable (except primitives) is always a reference (which has the start address of object) to an object only, Reference is never an object in itself.
For example
second = first;
is assigning a reference, so that first and second now refering to the same object. Objects are not copied, neither in assignments, nor in argument passing (what is copied/assigned is the reference).
Related
I am using Java
public class MapsConfusion {
public static void main(String[] args) {
HashMap< Integer, ArrayList<String>> map = new HashMap<>();
for (int i = 0; i < 15; i++){
ArrayList<String> lst = new ArrayList<>();
lst.add("something");
lst.add("something2");
map.put(i, lst);
}
for(int j = 0; j < 11; j++){
System.out.println(map.get(j));
}
}
}
The way this works is, it creates a new arraylist each time it loops around. Here is my question,
Thinking about pointers, when you declare a new Arraylist<> each time, you are creating a new Arraylist at a new address am I correct?
Other question: Doesn't the list only exist within the scope, which is the for loop? Then how is isstill accessible when I do the other (last) for loop?
1 Question
Yes, you always create a new object and therefore a new address.
See this for further information: https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
2 Question
The ArrayList exists as long as at least one variable pointing at it. In this case as long as map exists and the main method runs.
Here's more about the life cycle of an object: http://www.dummies.com/programming/java/the-life-cycle-of-a-java-object/
when you declare a new Arraylist<> each time, you are creating a new
Arraylist at a new address am I correct?
Yes you are right. Each ArrayListis created at a new memory location.
Doesn't the list only exist within the scope, which is the for loop?
Then how is is still accessible when I do the other (last) for loop?
It's accessible because each newly created ArrayList gets added in to your map and that's why you do not lose it when your first for loop ends.
If you do not add each newly created ArrayList in your map, you won't be able to access any ArrayList outside the first for-loop in which it is created.
Thinking about pointers, when you declare a new Arraylist<> each time,
you are creating a new Arraylist at a new address am I correct?
Correct.
Doesn't the list only exist within the scope, which is the for loop?
Then how is is still accessible when I do the other (last) for loop?
An object is automatically deallocated by the garbage collector only when there are no references pointing to it. In your case the list is added in map, therefore it is not deallocated since there is an element of map pointing to it.
Thinking about pointers, when you declare a new Arraylist<> each time,
you are creating a new Arraylist at a new address am I correct?
Yes you are correct the pointer to the List lst only exists in the scope of the first loop.
Other question: Doesn't the list only exist within the scope, which is
the for loop? Then how is isstill accessible when I do the other
(last) for loop?
But you assigned the object the pointer lst was pointing to, into the Map map outside the looop. Therefore the object still exists because the mapentry is pointing to it.
If you move the Map also into the first loop you will get a compile error.
Since you have not removed all references to the arrayList, it will still exist and remain accessible after the first for loop. The fundamental difference is:
the arrayList won't be accessible by any variable/pointers which you have declared within the for loop, as those variables are within the scope of the first for loop only.
During the run of the first for loop, you have pointed the hashmap's value entry to each individual list and apparently the hashmap is accessible beyond the scope of the for loop.
Converging from the above two points, all arrayLists are accessible from references made in HashMap's value
I am new to Java and I have just dealt with object arrays. I'm curious as to why Java requires me to use the following syntax for arrays
SomeClass[] object = new SomeClass[50]; // any positive integer works
object[2] = new SomeClass(some, parameters);
As I understand it, the new keyword allocates the data for the instance in memory. I was wondering why Java uses the new keyword twice here. I think it should only have to use the new keyword once when the objects are initialized and not when they are declared. So, my question is: why does Java use the new keyword twice when creating object arrays?
Here, the new keyword is used twice because two objects are being created -- one array and one SomeClass that happens to be placed in the array.
The first one is to create an array of references. The second one is to create the actual object for every element in the array.
You need to create the container (an array in your case), and each element (which is also an object) that you intend to place in that container.
In your case, I note you've created an array with 50 elements. That means that you can index object[0] up to and including object[49]. When the container is created, each object[n] will be a null reference.
SomeClass[] object = new SomeClass[50];
allocates an array with 50 uninitialized references
object[2] = new SomeClass(some, parameters);
allocates and instantiates an object referred to by the third index in the array
I have an object stored in a global variable let's say:
static ArrayList<Object> list = new ArrayList<Object>();
I want to store it later to look into it without actually changing the values in the structure itself. So I am doing something similar to this:
public void someMethod()
{
ArrayList<Object> tempList = new ArrayList<Object>();
tempList = list;
list.remove(0);
}
I'm thinking this may have something to do with me initializing the variable as "static". I don't usually do that but Eclipse told me I had to so I just let the change happen.
My understanding would be that I am storing the original list into a temporary list and anything I do to the temporary list would be independent of the original list. But it appears that if I were to remove something from this above list, that the original list is removing it as well.
I remember learning that this could happen sometimes but I think I've done this before without having that issue.
I apologize if this is a repeated question but the way I worded it didn't show me an question that was similar.
Thanks!
My understanding would be that I am storing the original list into a temporary list and anything I do to the temporary list would be independent of the original list.
This is not the case. When you do something like
a = b;
then both a and b refer to the same object. Mutations in a show up in b and vice verse (since there is only a single object in question). In this case you probably want to use the copy constructor of ArrayList:
ArrayList<Object> tempList = new ArrayList<Object>(list);
Notice that here we are explicitly creating a new, independent object and assigning that to tempList.
Note that this creates what's called a shallow copy: the objects referenced by the list themselves are not copied, but instead a new list is created that contains the references to the same objects as the original list.
At the end of your someMethod, your tempList disappears into the dark void of the GC. If you want to keep it, you need to turn it into a similar field as list is.
Also, assigning list to tempList makes you have two references to the same object.
I have encountered a problem in one of my Java projects, which causes bugs.
The problem sounds as following:
I have two arrays. Let's name them firstArray and secondArray. Object in this case is a seperate class created by me. It works, the array can be filled with objects of that type.
Object[] firstArray= new Object[];
Object[] secondArray = new Object[];
Now, when I get an element out of the first array, edit it and then copy it in the second array, the object from the first array gets altered too.
tempObj = firstArray[3];
tempObj.modifySomething();
secondArray[3] = tempObj;
Whenever I do this, the (in this case) 3rd element(actually 4th) of the first array gets the modifications. I don't want this. I want the first Array to remain intact, unmodified, and the objects I have extracted from the first array and then modified should be stored in the second so that the second array is actually the first array after some code has been run.
P.S. Even if I get the element from the first array with Array.get(Array, index) and then modify it, the element still gets modified in the first array.
Hopefully you understood what I wanted to say, and if so, please lend me a hand :)
Thank you!
You're going to have to create a new object.
The problem is the modifySomething call. When you do that, it alters the object on which it's called. So if you've only got one object (even by two names), you can't call modifySomething or they will both change.
When you say secondArray[3] = firstArray[3], you aren't creating a new object: you're just assigning a reference. Going through an intermediate temporary reference doesn't change that.
You'll need code that looks like this:
Object tempObj = firstArray[3].clone();
tempObj.modifySomething();
secondArray[3] = tempObj;
The clone() method must return a new object divorced from the original but having identical properties.
When you retrieve an element from your array, you have a reference to it. So if you modify it, the modification are shered through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new Object and use its constructor to initialize its fields.
The object extracted from the first array needs to be cloned to create a new instance that is seperate. Otherwise the modification will affect the object in the first array as it is the same object.
When you retrieve an element from your array, you get a reference to it. So if you modify it, the modification are shared through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new method which take in input your retrieved object and return a new one alike.
In Java, when you do this secondArray[3] = tempObj;, you actually put the reference to the array, not the real object
So firstArray[3] and secondArray[3] point to the same real object
What you need to do is to create a new object that is identical to your original object, and put the reference of the new object to your secondArray
It might worth to point out that default clone() function only does a shallow copy, so if you have mutable objects in your object's fields, it might cause some problems. Take a look at this article about how to do a deep copy
Hey people i have this structure for the search tree
class State
{
//CLASS STATE
int value;
char[][] state; //the game Grid
State child[]; // children of current state, maximum is 8
State(char[][] src)
{
state=src;
child=new State[8];
}
this is the root node definition
State rootNode = new State(currentGrid);
rootNode.value=-1;
int v =maxValue(rootNode,depth);
after the end of recursion in the max value function the array in rootNode should not be edited since its the the first state but when i Display it i get an array filled with stuff which means that the rootNode.state passed by reference to the max value function :(
//i am trying to implement MiniMax Algorithm.
If you don't want objects that are passed as parameters to be changed, pass in a copy (or make a copy of the parameter inside the method).
Note that char[][] means you have an array of char arrays, i.e. you are working with objects and if you copy the first level you still might have a reference to the second.
Thus you might have to loop through the first level/dimension and copy all the arrays in there, like this:
char target[][] = new char[state.length][0];
for( int i = 0; i < state.length; ++i ) {
target[i] = Arrays.copyOf(state[i], state[i].length);
}
If you need, you can easily create a copy of the array through Arrays.copyOf
You can also create a deep copy. How to do this has been answered here: How to deep copy an irregular 2D array
Yes, Java passes references to arrays and not the array as a value. So if you give a reference to your internal state away, the receiver can change it and the change is "visible" in the source (in fact: it's only one array that has been changed and all reference holders will see the change).
Quick fix/solution: clone your state array and pass a reference to this clone instead of the original. This will keep your internal root state unmodified.