There are two problems with your code, and both of them are in your useLayout
method.
The first problem is that you are not comparing Strings
s correctly on this line:
if(currentLayout.layoutType == name) {
name
is a String
, and I assume currentLayout.layoutType
is too. Two String
s that are equal but not the same will not compare equal under ==
. As a result of this, your layoutVariants
list will quite probably be empty at the end of the for
loop.
This line should read:
if(currentLayout.layoutType.equals(name)) {
The second problem is that you don't correctly handle the case that the layoutVariants
list is empty. The problem is on this line:
if(layoutVariants != null) {
layoutVariants
will never be null, so the else
branch of this if
statement will never execute. Because layoutVariants.size()
will be zero, rand
will always be zero. Trying to get the element at index 0 in an empty ArrayList will give you precisely the IndexOutOfBoundsException
you are seeing.
I imagine you want the else
block to execute if the layout name given isn't recognised, in other words, if the layoutVariants
list is empty, rather than null. In that case, change this line to
if(!layoutVariants.isEmpty()) {
Note the !
(not-operator) before layoutVariants
. You want the code under the if
statement to run if the layoutVariants
element is not empty.
EDIT in response to your comments: a null
ArrayList is very much not the same as an empty one. null
is a special value meaning that the variable doesn't have an object of a given type.
Let's try a real-world analogy: a shopping bag. If you have an empty bag, or no bag at all, then you have no shopping either way. However, you can put things into an empty bag, and count how many items it contains, for example. If you don't have a bag, then it doesn't make sense to put an item in it, as there's no bag to put the item into. null
represents the case where you don't have a bag.
Similarly, a String
is a collection of characters, and the collection of characters can exist even if it doesn't contain any characters.
isEmpty()
can be used for any collection, and, if you're using Java 6 or later, Strings as well. Off the top of my head I can't name any other classes that have an isEmpty
method. You'll just have to consult the documentation for these classes to find out.
I've not worked with Processing much, but I am aware that Processing is built on Java, so I would expect any standard Java method to work. Also, I wouldn't worry about 'clearing' a variable: the JVM is generally very good at clearing up after you. There's certainly nothing I can see wrong with your code in this respect.
EDIT 2 in response to your further comment: ArrayList arr;
declares a variable of type ArrayList
. However, the variable arr
is uninitialized: it does not have a value (not even null
) and it is an error to try to read the value of this variable before you have assigned a value to it:
ArrayList arr;
System.out.println(arr); // compiler error: arr might not have been initialised.
Assign null
and the code then compiles:
ArrayList arr = null;
System.out.println(arr); // prints 'null'.
It's not often you need to declare a variable and not give it a name, but one common case is where you want to assign different values to the same variable on both sides of an if
statement. The following code doesn't compile:
int y = getMeSomeInteger(); // assume this function exists
if (y == 4) {
int x = 2;
} else {
int x = 5;
}
System.out.println(x); // compiler error: cannot find symbol x
The reason it doesn't compile is that each variable x
is only available within the braces {
and }
that contain it. At the bottom, neither variable x
is available and so you get a compiler error.
We need to declare x
further up. We could instead write the following;
int y = getMeSomeInteger(); // assume this function exists
int x = 0;
if (y == 4) {
x = 2;
} else {
x = 5;
}
System.out.println(x);
This code compiles and runs, but the value 0
initially assigned to x
is never used. There isn't a lot of point in doing this, and we can get rid of this unused value by declaring the variable but not immediately giving it a value.
int y = getMeSomeInteger(); // assume this function exists
int x;
if (y == 4) {
x = 2;
} else {
x = 5;
}
System.out.println(x);