Java giving out of bounds exception when calling function twice? - java

I'm trying to find out if there is a variable that exists at some point in an ArrayList, but, when calling the function that does this, twice, I get an java.lang.IndexOutOfBoundsException. But when the function is called only once, it doesn't give an error, even though, when calling the function twice, they check to see if different indexes exist, not the same one.
Code;
//package mj.mjo.Vars;
public boolean varExists(int index){
return mjo_vars.get(index) != null;
}
Note, mjo here is a variable, with vars being another variable that is the mj.mjo.Vars class
//package mj.play.StudioCanvas;
int nonsys = mjo.vars.setVar("TEST", "LOLOLOL", false); // returns 1
int yessys = mjo.vars.setVar("SYSVARTEST", "WOOHO!", true); // returns 2
System.out.println("DOES THE VAR \"TEST\" EXIST? " + mjo.vars.varExists(nonsys));
System.out.println("DOES THE VAR \"TEST\" EXIST? " + mjo.vars.varExists(yessys));

The error indicates that the value of index that you pass to get() is greater than or is equal to the number of elements in the list. Change your code as follows to avoid the exception:
public boolean varExists(int index){
return index >= 0
&& index < mjo_vars.size()
&& mjo_vars.get(index) != null;
}
In general, the error means that something is wrong with your indexing scheme: list and array indexes in Java start at zero, and end at size()-1, inclusive. If passing 2 triggers the exception, but passing 1 is OK, then the list has only two elements - at indexes 0 and 1.

Related

Conditional and iterators in ruby

I'm trying to translate the following code into ruby:
public void discardWeapon(Weapon w){
if(!weapons.isEmpty()){
boolean discarded = false;
Iterator<WeaponType> it = weapons.iterator();
while(it.hasNext() && !discarded){
WeaponType wtaux = it.next();
if(wtaux == w.getWeaponType()){
it.remove();
discarded = true;
}
}
}
}
But, when it comes to the while loop, I can't really find a practical way to do it in ruby. I've got the following structure so far:
def discardWeapon(w)
if(!#weapons.empty?)
discarded = false
#weapons.each do |wtaux|
end
end
end
But, how can I check my condition is met when using the .each iterator?
Thanks in advance.
I am not sure if I read your Java code correctly, but it feels to me like you have an instance variable #weapons that holds an array of weapons and you want to discard one instance of a weapon w from that list.
def discard_weapon(weapon)
index = #weapons.index(weapon)
#weapons.delete_at(index) if index
end
Array#index returns the index of the first match. And Array#delete_at deletes the element at the index when there was an element found.
When it is possible that the same weapon is included in the array multiple times and you want to discard all matching weapons then you can use the following one-liner:
def discard_weapon(weapon)
#weapons.delete(weapon)
end

Working of Return statement in a method in Java

I am trying to understand the working of return statement in JAVA.
My doubt is if inside a method with a Non void return type, I have a decision block which also has a return statement of its own, Still I have to return some value .
For understanding here is a sample code I have written :-
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count1;
}
return count2 ;
}
In the mentioned code I just want to return the no. of bunnies which I am being able to do from inside the bunnyEars method count1. But still JAVA wont allow to have a non-void method without a return type which is totally understood and I have to add count2 return also. Now I am suspecting that I am having a conceptual understanding failure here. Kindly let me know if I am missing something? Kindly let me know If I am missing some more info here.
[Edited] Full code:
public class Test5 {
//public int ears=1;
public int count=0;
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count;
}
return count ;
}
public static void main(String args[]){
Test5 test5= new Test5();
System.out.println(test5.bunnyEars(90));
}
}
Yes you need to return count2 which should be zero. Which means if there are no bunnies then there are no ears. So which returning you should be returning some value irrespective of the conditional block.
So in this case
return count1;
represents the number of ears if the bunnies are represent, while
return count2;
represents the number of ears when there are no bunnies, which should be 0.
I hope that gives you some clarification
I think your conceptual misunderstanding lies with understanding the flow of the program.
Supposed you were to use this method by calling:
bunnyEars(2)
Then, once you enter the method, the first thing the program does is check if 3 >= 1. Since this is true, you proceed into the code inside the {..} (called a 'block'). Inside this block, you increment count by 2. I am assuming count is defined elsewhere in the class, but suppose the current value for count is 10. Then, the new value of count will be 12.
After this, the program executes the line:
bunnyEars(bunnies - 1)
Which translates to:
bunnyEars(1)
Now, basically, you are calling the same method again, but passing in 1 instead of 2.
Once again, the program checks to see that 1 >= 1, which is true. So it goes into the
if-block which, again, increments count by 2. So now, count = 14. Then it calls the
same method again but this time passing in 0.
bunnyEars(0)
Since 0 >= 1 evaluates to false, you the program skips the if-block and continues
execution after the block. So know, you are in the method bunnyEars(), but you have
completely skipped over your "return" statement. But, alas, bunnyEars MUST return an int.
So this is why you must have a return after the block. In your case, bunnyEars(0) returns count2 and the program-execution returns to where you called bunnyEars(0).
Read up on recursive calls. The basic idea of a recursive method is that, inside the recursive method, you must have some case that terminates the recursion (otherwise you will loop forever).
For example, the following code will go on forever:
public int sum(int in)
{
return in + sum(in - 1);
}
This will keep going on forever, because sum(1) will call sum(0) which calls sum(-1).
So, I must have a condition that terminates the recursion:
public int sum(int in)
{
if(in == 0) return 0;
return in + sum(in - 1);
}
Now, I have a terminating-case. So if I call sum(1), it will call sum(0) which returns 0. So my result is 1 + 0 = 1.
Similarily,
sum(2) = 2 + sum(1) = 2 + 1 + sum(0) = 2 + 1 + 0
sum(3) = 3 + sum(2) = 3 + 2 + sum(1) = 3 + 2 + 1 + sum(0) = 3 + 2 + 1 + 0 = 6
Hope this helps!
So as I understand it, your question is why you still need to return count2 if you return count1. The answer is basically 'what happens if you don't enter the if block?'. In that case, without return count2, you wouldn't have a return value, which is what Java is complaining about. If you really don't want two return statements, you could probably do something like:
public int bunnyEars(int bunnies) {
int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
}
return count ;
}
On a side note, this and the code you posted in your question won't work for regression purposes, but the one in your comment does, and there it looks like you have a static variable for count, in which case you could set the return type to void and just print count.

InvocationTargetException while trying to add variables to a new object

I am trying to send two variables from one sketch to another, using the oscP5 library for processing.
The message I am sending is created like this:
OscMessage myMessage = new OscMessage("/test");
myMessage.add(title);
myMessage.add("Zeit");
oscP5.send(myMessage, remoteLocation);
In the second sketch, I receive the data like that:
void oscEvent(OscMessage theOscMessage) {
if(theOscMessage.checkAddrPattern("/test")) {
String title = theOscMessage.get(0).stringValue();
String layoutType = theOscMessage.get(1).stringValue();
addToQueue(title, layoutType);
}
}
And here my simplified addToQueue function:
void addToQueue(String title, String layoutType) {
if(!existsInQueues(title)) {
upcomingHeadlines.add(new Headline(title, printAxis, scrollSpeed, layoutType));
}
}
Every time I start the sketches, I get the error:
ERROR # OscP5 ERROR. an error occured while forwarding an OscMessage to a method in your program. please check your code for any possible errors that might occur in the method where incoming OscMessages are parsed e.g. check for casting errors, possible nullpointers, array overflows ... .
method in charge : oscEvent java.lang.reflect.InvocationTargetException
I have been able to track the problem down to the layoutType-Variable. If I change
String layoutType = theOscMessage.get(1).stringValue();
to
String layoutType = "Zeit";
no error occurs.
That is quite confusing, because both versions should have the same result.
The error message does not help me in any way.
Edit
I have compared the two possible variables like that:
String layoutType = theOscMessage.get(1).stringValue();
String layoutTypeB = "Zeit";
if(layoutType.equals(layoutTypeB)) println("Same String!");
Since gets printed to the console, both have to be the same … I really do not know where to search for an error anymore.
Edit 2
I have wrapped my second sketch in try {...} catch(Exception ex) {ex.printStackTrace();} like that:
void oscEvent(OscMessage theOscMessage) {
try {
if(theOscMessage.checkAddrPattern("/test")) {
if(debug && debugFeed) println("Received message from other sketch.");
String title = theOscMessage.get(0).stringValue();
String layoutTypeO = (String)theOscMessage.get(1).stringValue();
String layoutType = "Zeit";
if(debug && debugTemp) {
if(layoutType.equals(layoutTypeO)) println("IS DOCH GLEICH!");
}
if(debug && debugFeed) println("Parsed Information.");
if(debug && debugFeed) println("-----");
addToQueue(title, layoutTypeO);
}
} catch(Exception ex) {ex.printStackTrace();}
}
That gives me this error as result:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at printer$Headline.useLayout(printer.java:260)
at printer$Headline.<init>(printer.java:188)
at printer.addToQueue(printer.java:407)
at printer.oscEvent(printer.java:395)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at oscP5.OscP5.invoke(Unknown Source)
at oscP5.OscP5.callMethod(Unknown Source)
at oscP5.OscP5.process(Unknown Source)
at oscP5.OscNetManager.process(Unknown Source)
at netP5.AbstractUdpServer.run(Unknown Source)
at java.lang.Thread.run(Thread.java:744)
Edit 4
Constructor for my Headline-Class:
class Headline {
//Define Variables
Layout layout;
String title, lastHeadline;
float yPos, speed;
float transparency = 255;
boolean fullyPrinted = false;
int boundingBoxHeight;
// Initialize Class Function
Headline(String t, float y, float s, String lay) {
title = t;
yPos = y;
speed = s;
layout = useLayout(lay);
boundingBoxHeight = calculateTextHeight(title);
}
You might want to know about useLayout() too, so here it is:
Layout useLayout(String name) {
ArrayList layoutVariants = new ArrayList<Layout>();
int existingLayouts = layouts.size();
Layout chosenLayout;
for(int i = 0; i < existingLayouts; i++) {
Layout currentLayout = (Layout)layouts.get(i);
if(currentLayout.layoutType == name) {
layoutVariants.add(currentLayout);
}
}
if(layoutVariants != null) {
int rand = (int)(Math.random() * layoutVariants.size());
chosenLayout = (Layout)layoutVariants.get(rand);
} else {
chosenLayout = (Layout)layouts.get((int)(Math.random() * existingLayouts));
}
return chosenLayout;
}
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 Stringss correctly on this line:
if(currentLayout.layoutType == name) {
name is a String, and I assume currentLayout.layoutType is too. Two Strings 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)) {
See also this question.
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);

how to see if a arraylist is filled or not

Hello I am creating a application that uses arraylists ( practice purposes not real app )
I have created a method that gives me the answer of a math but only if the arraylist contains no object. for some reason I always see the else in my if/else construction.
Here is how I check if the array list contains objects
public void sluitRegistratie() {
aantalBezoekers = bezoeker.size();
if(!(aantalBezoekers >= 0)) {
String str = "Gemiddelde tijd bezoekers: " + (gesommeerdeTijd / aantalBezoekers);
JOptionPane.showMessageDialog(null, str);
}
else {
JOptionPane.showMessageDialog(null, "Bezoekers zijn nog niet weg");
}
}
ArrayList has an isEmpty() method that will return true if the arraylist is empty, false otherwise. So it looks like you want if(bezoeker.isEmpty())...
The size of an ArrayList can never be negative, so your check for !size()>=0 will never be true. Just check if size()==0.
if(!(aantalBezoekers >= 0))
Is the same as:
if(aantalBezoekers < 0)
In other words, when the length is less than zero, but this cannot happen.
if(!(aantalBezoekers >= 0)) {
Basically means that only execute if when aantalBezoekers is NOT greater than zero.
If you want to check if your list is of size zero use something like below:
if(bezoeker.size()>0){
System.out.pritnln("bezoeker is greater than zero " + bezoeker..size());
}
else {
System.out.pritnln("Mahn, my bezoeker is Empty " + bezoeker..size());
}
you could also simply use ArrayList.isEmpty() method to check if an arraylist is empty.
if(bezoeker.isEmpty()) {
An ArrayList can hold 0 elements at minimum, so !(aantalBezoekers >= 0) will always be false, and you'll always be in the else part.
thats because
!(aantalBezoekers >= 0)
means
not greater than or equal to zero
which is equivalent to
less than zero
which can never happen.

Java: Unpredictability with IndexOutOfBoundsException

I have a script which works fine, as far as I have programmed it. Within that script, I have a do-while loop within which there are two more do-while loops, one feeding to the other.
I have removed some code for clarity:
StockArray.stockCodeArray();// creates stockcode array
FileArray.fileListArray(); // creates array of file names to input into
// ImportFiles
ImportFiles.importAscii(); // reads file. if debug: creates importarray
do {
ObsHandler.obsPartsHandler(); // read part descriptions into temp
// array
ObsHandler.search();
} while (!endline.equals(null));
obsPartsHandler():
String numberline;
ObsHandler o1 = new ObsHandler("Part");
if (i < ImportFiles.importarray.size()) {
do {
numberline = ImportFiles.importarray.get(i); //editted here
i = i + 1;
} while (!numberline.startsWith(".Number"));
i = i + 1; // set i to second line of part description
do {
i = i + 1; // set i to next line
} while (!numberline.equals(""));
if (i < ImportFiles.importarray.size()) {
endline = ImportFiles.importarray.get(i);
System.out.println(endline);
}
}
All variables have been initialised. The search() method is currently blank.
As I go through the loops, there a print streams, that I have ommitted, which indicate that the loops are functioning correctly.
The problem I have is, when I run the program the OutOfBoundsException I am expecting from the if statement in obsPartsHandler is unpredictable in it's location on the console. I am wondering if, but still assuming that, this is something I have done wrong.
If I have removed too much code, please comment and I will add it back in.
Exception:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 307, Size: 307
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at ams.ObsoletePartsHandler.org.ObsHandler.obsPartsHandler(ObsHandler.java:58)
at ams.ObsoletePartsHandler.org.ObsHandler.main(ObsHandler.java:35)
Why are you worrying about where the exception message appears though? The user should never be faced with your debug prints nor stack traces from your exceptions.
Exception traces and regular prints are normally sent to two different output streams (System.err and System.out respectively), messages will not necessarily be synchronized between the two. flush()-ing the stream after printing to it may help. That said, if you are expecting the exception, you should probably either code to avoid it preemptively or catch it with Java's exception handling.
if (i < ImportFiles.importarray.size()) {
do {
numberline = ImportFiles.importarray.get(i);
i = i + 1;
} while (!numberline.startsWith(".Number"));
//...
Let's assume importarray contains 3 lines: aaa,foo and bar. If i starts at 0. What will happen?
It will set linenumer to aaa and test if it starts with ".Number" . Then set it to foo, set it to bar. Now the line is still not found, so i becomes 3, but there is no 4th line, thus an exception is throw. (First item has index 0, so 4th item has index 3.)
You could make a function for those 4 lines of code that do what you need:
private int getLineStartsWith(List<String> list,String startsWith,int offset) {
for (int k = offset; k < list.size(); k++)
if (list.get(k).startsWith(starsWith);
return k;//line found
return -1;//line not found
}
Just return -1 if the line is not found in the list. Then your function can be written as:
i = getLineStartsWith(ImportFiles.importarray,".Number",i);
if (i == -1)
'Not found'

Categories

Resources