I have an ArrayList that I am adding objects to. Objects are added by using a textbox.
The problem I have is when user enters a value into the textbox, all the entries in my ArrayList take on the new value.
if(e.getSource() == textbox){
String name = textbox.getText();
NameSurferEntry entry = new NameSurferEntry();
entry = db.findEntry(name);
graph.addEntry(entry);
graph.update();
textbox.setText("");
}
Code to add entry:
public void addEntry(NameSurferEntry entry) {
entryArray.add(entry);
}
You're creating a new NameSurferEntry which you on the next line overwrite with a value from your database. If the returned entry is always the same your arraylist will only contain references to the same object.
NameSurferEntry entry = new NameSurferEntry();
entry = db.findEntry(name);
What you should consider is trying to achieve immutability in your objects and/or perform defensive copying. For simple properties it's enough to declare them final, but for complex elements you would typically need to copy the object by creating it anew.
The following sample should work for you, given that you implement the copy constructor
NameSurferEntry copy = new NameSurferEntry(db.findEntry(name));
This means that db.findEntry always returns the same NameSurferEntry instance, and just replaces the name inside it with the name it receives as argument.
Adding an object to an list only adds a reference to the object in the list. It doesn't clone the object to store a copy of it in the list.
BTW, why are you creating a new NameSurferEntry and assign it to the entry variable if it's just to overwrite it with the result of db.findEntry afterwards?
Whatever this is:
entry = db.findEntry(name);
contains and returns one object, and you're changing whatever it contains.
To be more clear: You're adding the same reference to your list over and over, and changing the contents of the single object that reference points at.
Related
calls is an arrayList, customerCalls is a hashMap. I was debugging using eclipse and I fount that calls.clear clear the arrayList object already inserted in the customerCalls Hashmap. I am confused because I thought that once the object was submitted to another data structure, it has an independent entity and no operations can be taken on it unless I access this data structure containing it.
I need to clear the arrayList calls to make it free for a new set of calls that would be dedicated to another contract and later inserted as value for the hashmap key (contract Number). Not clearing it accumlates all calls as it appends current iteration addition to the past iteration one.
> if (callContractID.equals(currentContractID)==false){
> customerCalls.put(currentContractID, calls);
> currentContractID = callContractID;
> calls.clear();
> calls.add(call);
> count++;
> }
else {
calls.add(call);
}
Passing a reference to object A to another object in no way alters A (unless the other object explicitly invokes a method on A to change its state, of course). It doesn't spawn an independent copy of A, or make A immutable, or anything like that.
It sounds like what you want to do is to just create a new ArrayList once you're done with the first one and have submitted it to the map.
if (!callContractId.equals(currentContractID) {
calls = new ArrayList<Call>(); // or whatever the type is
// rest of your code...
}
This will replace the value of calls with a reference to a new, empty ArrayList that you can add new elements to. The old ArrayList will still be available to the HashMap, because the map has its own copy of the reference to that first list.
I am confused because I thought that once the object was submitted to another data structure, it has an independent entity and no operations can be taken on it unless I access this data structure containing it.
No. The map contains a reference to an object... just as if you simply assigned another variable to it. You can have lots of references to the same object, and any changes made via one reference will be seen via any of the others. As a very simple example:
StringBuilder b1 = new StringBuilder();
StringBuilder b2 = b1;
b2.append("foo");
System.out.println(b1); // Prints foo
The exact same thing happens with collections:
StringBuilder b1 = new StringBuilder();
List<StringBuilder> list = new List<StringBuilder>();
list.add(b1);
StringBuilder b2 = list.get(0);
// Now b1 and b2 are both reference to the same object...
b2.append("foo");
System.out.println(b1); // Prints foo
Not at all. The object has not been "submitted", it has been passed to another method (it happens that such method has made its own copy of the reference to the object.
All references to the object point to the same object and may call the same methods. The object (usually) has no means to know where it is being called from.
I'm new to Java and been trying to figure out if I need to pass a new instance of a class when adding the entry to a list, as such:
CCustEntry entry = new CCustEntry();
List<CCustEntry> CustList = new ArrayList<CCustEntry>();
do
{
// set all entry fields
entry.id = [...];
[fill other fields of entry from DB]
// add entry (constructor copies entry)
CustList.add( new CCustEntry( entry ) );
} while( C.moveToNext() == true );
OR... can I remove new and simply pass entry to the add() method like this:
CustList.add( entry );
I've been reading about Lists but I'm more confused than I was before. Coming from Delphi and C++, I'm fine with the syntax, but some of the "grammar" of Java still has me scratching my head.
Thanks for any help.
It depends if the entry will be modified or not. It sounds like you have a bean that makes a shallow copy of the entry, so if the fields of entry will be modified, then you should add a copy. Otherwise, it would be just wasting memory to construct a new one.
Here, it seems like you are using the same entry throughout the loop, so you will want to make a copy. Otherwise, the whole list will contain the same object - i.e., each item is the same object.
Another comment: in Java, it's usual to name fields and values starting with a lowercase letter.
It depends: if you don't create a new instance each time, then you will be adding the same instance to the list multiple times. This means that if you modify an element at one index of the list, then all of the other elements will also get modified in the same way (since they are all the same instance). If you want distinct but equal instances, then you must create a new one each time.
This is a little confusing question for me to express, but I'll do my best.
So:
ArrayList<Object> fieldList = new ArrayList<Object>();
I then dump a lot of different variables to this array:
fieldList.add(objectsURL); //string
fieldList.add(X); //int
fieldList.add(Y); //int
...
If I change the variable, the values in the array change
too-confirming the array stores a reference to the memory, rather
then value itself.
However, if I then retrieve data from the array then set that...
Object object = ((String)this.fieldList.get(0));
Then set object
object = "meeep!"
objectsURL is not set to "meep!" but rather it retains its original
value.
I assume this is because the "object" is not referencing the original
variable anymore, that instead its pointing to a new immutable string
in the memory.
All expected Java behavior I think....but then, how would I go about
setting the actual original variable? is this possible in java?.
So, in other words. Given only access to "fieldList" is it possible to change the value of
"objectsURL"?
So, if:
String objectsURL = "www.google.com"
fieldList.add(objectsURL);
Is there a way to set objectsURL to "www.stackoverflow.com" using only a reference from fieldList?
I dont want to change the fact that fieldList contains "objectsURL", I want to change what string the variable "objectsURL" actualy contains.
If not, is there an alternative method to achieve the same thing?
I hope my question explains the problem well enough.
My use-case is trying to make a serialization/
deserialization system for a bunch of my objects. I was hoping to put
all the fields into a arraylist I could retrieve for both reading and
writing....thus avoiding having to hard-code long lists of
field[0]=blah and blah=field[0] and then going though constant pains
of needing to renumber them each time I add a new field before
another.
(I cant use Javas inbuilt serialization, as I am using GWT and this is client side only.)
Thanks,
I assume this is because the "object" is not referencing the original variable anymore, that instead its pointing to a new immutable string in the memory.
Correct, each time you use the assignment operator = on an object you change the object it refers to, not the object itself.
To change the values in the List, you use the .set method of an ArrayList
this.fieldList.set(0, newValue);
Since your variable is a String, there is no way you can change the String-variable through the list
Your alternatives:
using a char-array
List myList = new ArrayList();
char[] charArray = "My String".toCharArray();
myList.add(charArray);
charArray[0] = 'A';
String theString = new String(myList.get(0)); // "Ay String"
If you use a char-array, make sure that the length of the array is enough to contain the number of characters you want to have in the future, because to change the length of the array you will need to create a new array (array lists can be expanded dynamically, arrays can not)
Embed the String inside your own class (I have ignored getters and setters here)
class MyString {
public String value;
public MyString(String value) {
this.value = value;
}
}
MyString myStr = new MyString("some value");
list.add(myStr);
((MyString) list.get(0)).value = "a new value";
System.out.println(myStr.value); // will print "a new value"
Strings are immutable, so it is impossible to change the contents of a String object. Also, you cannot use the list to change what object the reference variable objectsURL points to. To achieve what you want, you will need to create a custom class that has a String member. You can then store instances of this class in a List and change the String references to via the references in the list. The changes will then be reflected in any other reference variables which refer to the objects in the list.
First, you declare a variable 'object' and assign some Object out of the ArrayList. Later you assign some other object "meeep!" to this variable. There is no reason that your 'object' variable is related to the ArrayList.
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
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).