Java and ArrayList - really simple fix i think, please help

Associate
Joined
21 May 2003
Posts
1,008
Hi there. I'm trying to use an ArrayList to add different objects (in this case Animals). each Object can be a specific type (in this case Sheep), and each individual object has its own values (i.e. there can be many Sheep but they all have their own tag).

when I use the code below, I can add an object fine, but when I add another Object that is the same type, all the details of previously added objects change to the one being entered. i.e from the code below I get:
Code:
Object Added: 0 Tag 1
Object Added: 0 Tag 2
Object Added: 1 Tag 2

So the first object was added and the tag was 1, but when i added the second, the tag became 2 for the first object as well. why is this? it's like "tag" is set to static but it isn't.

heres the code (the two for loops are just to print out the tags for debugging):
Code:
import java.util.*;
 
abstract class Animal {
    public abstract int get_tag();
}

class Sheep extends Animal {
	int tag;
	public void Sheep(int t){
		tag = t;
	}
	
	public int get_tag(){
		return tag;
	}
}


public class NativityScene {
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<Animal>();
	
	Sheep sheep = new Sheep();
	sheep.tag = 1 ;
        animals.add(sheep);
	
	int num_objects = animals.size();
	for (int j = 0; j<num_objects; j++){
		System.out.println("Object Added: "+j+" Tag "+animals.get(j).get_tag());
	}
	
	sheep.tag = 2 ;
	animals.add(sheep);

	num_objects = animals.size();
        for (int j = 0; j<num_objects; j++){
		System.out.println("Object Added: "+j+" Tag "+animals.get(j).get_tag());
	}
    }
}

Any help is appreciated
 
You're updating the same object, hence the problem. Don't forget that the variable sheep will be a reference to the same instance of Sheep that you added to the list with tag = 1, so when you assign sheep.tag = 2, you are updating the same object that was added with tag = 1, and then adding it again.

You'll need to either:
Code:
Sheep sheep2 = sheep.clone();
sheep2.tag = 2;
animals.add(sheep2);
or:
Code:
Sheep sheep2 = new Sheep();
sheep2.tag = 2;
animals.add(sheep2);

HTH :)
 
ok your method works but then I'm stuck as to what to do. the problem is I don't know how many objects I'm going to have (they're going to be read from a file), so I was just going to look out for the word "sheep" for example, and then call the code to add it to the list.

is there a way i can add a new variable everytime that has a number in it thats always one more than the previous? (i.e. if a Sheep5 exists then the next one should be Sheep6).
 
The way you have written your initial code is a bit erratic, can you expand the scenario and explain what the data from this list comes from in more detail?

The code below is how I'd write the code you have written, the Sheep class now has a constructor so you can set the tag during construction. I've also inserted a new object directly into the list rather than storing it in a variable beforehand which isn't necessary. It seems like you need to perform the insertion of objects in a loop which I can't really help with until you expand on where you are getting the data from and how it is extracted from the source.

Code:
import java.util.*;
 
abstract class Animal {
    public abstract int get_tag();
}

class Sheep extends Animal {
	private int tag;
	public Sheep(int t){
		tag = t;
	}
	
	public int get_tag(){
		return tag;
	}
}


public class NativityScene {
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<Animal>();
	
        animals.add(new Sheep(1));
	
	for (int j = 0; j<animals.size(); j++){
		System.out.println("Object Added: "+j+" Tag "+animals.get(j).get_tag());
	}
	
	animals.add(new Sheep(2));

        for (int j = 0; j<animals.size(); j++){
		System.out.println("Object Added: "+j+" Tag "+animals.get(j).get_tag());
	}
    }
}
 
the data will be coming from an external txt file, but i haven't implemented that yet.

the file is just going to have the list of the animals, with the first argument being the animal type, the next tag, and s on:
Sheep 1
Sheep 2

but i don't know how many sheep there will be.

your code looks good but i still can't see how i can just append a new sheep into the list. i thought once you stored a variable into an arraylist, the variable can be destroyed as all the information is at arraylist(index).
 
Yes the information is in the ArrayList but you can still access it using a loop. I can't think why you would want to have a variable that points to each animal, that is what collections (or arrays if you want to be general) are designed for.

The way I understand it is you would read you file line by line and after each line you would perform an operation that inserts the data read into the collection if it meets a certain condition (eg. it contains the word sheep etc.). You can access and append data into collections at any time. The print statement in your original example is a classic way of iterating over a collection.

Can you explain why you think you need a variable for every item you want to put into the collection? I have a feeling you are a little confused on how the collections and variables work which is understandable if you're new to Java or programming, it took me quite a while to understand why anyone would want to use an array several years ago when I started programming.
 
Hi,

One thing you could do to simplify the creation of the animal objects is to use a factory class that produces the animal objects for you.

The factory class would contain a method that takes the entire line read in from the file and returns an object of type Animal. Code within the method would look at the line passed in, decide which type of object to create, create the object of that type (using the constructor approach shown by Rob), and return it to the calling code. The returned object can then be added into the array.

So, you'd have something like:

Code:
class AnimalFactory() {
    public Animal createAnimal(String t) {
        String animaltype = /* Get animal type into this string */
        Animal obj = null;

        if (animaltype.compareTo("Sheep")==0) {
            obj = new Sheep(t);
        } elseif (animaltype.compareTo("Donkey")==0) {
            obj = new Donkey(t);
        }
        return obj;
}
And in your main code:

Code:
AnimalFactory myfact = new AnimalFactory();
List<Animal>animals = new List<Animal>();

while there are still lines to be read {
    Animal a = myfact.createAnimal(linereadinfromfile);
    animals.add(a);
}

or you could shorten the bit in the loop down to:

animals.add(myfact.createAnimal(linereadinfromfile));

Hope that helps and doesn't confuse. I'm trying to split out the object creation problems from the array handling problem.

Jim
 
Back
Top Bottom