I don't spot any mistake on this code, however eclipse tells me that the variables are not initialized. It is only a warning, but after compiling it doesn't work either. I simply can't find the mistake and thing of this code being 100% correct. Please note that the structure of this code can not easily be changed because the code provided below is simplified so you do not have that much to read ;-)
int min1; float somefloat;
try {
//setting values for min and somefloat
min1 = 1;
somefloat = 0.92f;
} catch (IOException ioe) {
System.err.println("Read Exception");
}
while (true){
//warning: variables min1 and somefloat may not be initialized.
float value1 = (1023 - min1) * somefloat;
System.out.println("Value: " + value1);
}
You have to initialize all your variables before they enter any try block. The Java compiler does not know that in your case, there is no way of an exception to be caused.
So theoretically speaking, there could be an exception somewhere which leaves your variables uninitialized. And that's not acceptable. Thus the warning.
Just initialize your variables to zero.
int min1 = 0;
float somefloat = 0f;
Compiler doesn't analyse if in concrete case the variables would be initialized or no. It assures that if the variables are initialized only in try, and not in catch or finally it would assure they may be not initialized.
Give a similar try with "obvious" condition like if(1>0) {}. The compiler compiles and not makes the analysis of your code. While for human it is obvious that something will happen, the java compiler have no code to detect such cases, neither it is specified by java syntax. So you're expecting from the compiler the AI it doesn't have, to keep the compiling clear, predictable and fast.
Your code has, BTW, error that will be reported instead of this you describe, because there's no place IOException can be thrown.
however eclipse tells me that the variables are not initialized
The warning is shown cause it is a possiblity that exception is thrown before the variable are initialized within try. then within while the variables remain uninitialized.
They should have an initial value just in case if it enters the catch block. Try this:
int min1 = 0; float somefloat = 0f;
try {
//setting values for min and somefloat
min1 = 1;
somefloat = 0.92f;
} catch (IOException ioe) {
System.err.println("Read Exception");
}
while (true){
//warning: variables min1 and somefloat may not be initialized.
float value1 = (1023 - min1) * somefloat;
System.out.println("Value: " + value1);
}
You have to initialize them while declaring them or at least outside the try-catch block. Because compiler cannot be sure the initialization inside the try-catch block is going to complete normally, in which case, you will be having an un-initialized variables outside.
int min1=0; float somefloat=0.0f;
you need to initialize the variables during declaration.variable assignment in try will overwrite that value and if any exception occur(Don't know how in your case..) it will take the default value. during compilation, compiler will not look at your code whether it will throw an exception or not (except throw , it requires a matching catch) so it needs an explicit initialization .
private void tset(){
int min1; float somefloat;
try {
//setting values for min and somefloat
min1 = 1;
somefloat = 0.92f;
while (true){
//warning: variables min1 and somefloat may not be initialized.
float value1 = (1023 - min1) * somefloat;
System.out.println("Value: " + value1);
}
} catch (Exception ioe) {
System.err.println("Read Exception");
}
}
This may be the code you are looking for...
Related
UPDATE: sorry for misleading some of you, here is more detailed code:
I'm trying to parse String[] array to int[] array. I take String from JTextArea, make String[] and then int[].
array1String="asd, lala, 22";
array2String="1,2,3";
String [] arr1 = array1String.split(",");
String [] arr2 = array2String.split(",");
int[] array1 = new int[arr1.length];
for (int i=0; i<arr1.length; i++) {
try {
array1[i] = Integer.parseInt(arr1[i]);
} catch (Exception ex) {
resultLabel.setText(ex.getMessage());
}
}
int[] array2 = new int[arr2.length];
for (int i=0; i<arr2.length; i++) {
try {
array2[i] = Integer.parseInt(arr2[i]);
} catch (Exception ex) {
resultLabel.setText(ex.getMessage());
}
}
the parseInt() method interprets any gibberish as a "0". So instead of getting an exception, I get every int[] member corresponding to gibberish String[] member as a ZERO. But that's not what I want. I want to catch the exception to pass the message to the JLabel. I don't want it to happily eat any nonsense and make it "0". Am i missing something? I suspect that is not how this is supposed to work.
result arrays look like the
array1 [0,0,22]
array2 [1,2,3].
And nothing goes to Label, as if exception never happened. By i didn't change the code, only handling the exception changed.
The code setting the text of the JLabel is missing, but I guess it's after the try-catch-block and will simply use the value of x, which is 0 by default. The preferable solution to this problem is to update the text inside the try-catch-block like this:
try{
int x = ...
resultLabel.setText("" + x);
}catch(Exception ex){
resultLabel.setText(ex.getMessage());
}
In general, if generating data might throw an exception is recommended to process the data inside the try-catch-block the data is produced in.
EDIT:
There's one simple problem with this code: int doesn't have any properties like an undefined value. The simplest approach to this would be to use an Integer[] instead and null as undefined-value:
Integer x;
try{
x = ...;
}catch(Excpetion ex){
resultLabel.setText(ex.getMessage());
x = null;
}
The default value for int is 0. Since you get an exception and nothing is assigned to x, you get 0
Firstly, if you are using int x = Integer.parseInt(str); in TRY block then it means your x becomes local variable of your TRY block and you cannot use it outside of TRY, not even in CATCH block. So, the in case of exception, question of x=0 will not even come because x would have lost its scope.
And if you are declaring x outside of TRY block (so that you can use it inside CATCH or outside TRY block) then you have initialize it (ofcourse with value as 0 or -1) then x=0 or x=-1 should be expected value of x
Your concern:
I want to catch the exception to pass the message to the JLabel.
Consider below approach, where you are catching the exception, computing the error message and then passing/setting into your label field etc.
Advantage of this approach as opposed to other is that you need to have duplicate code of resultLabel.setText(), you are updating your labelMessage with either success message or failure message and using it.
Please feel free to let me know if this doesn't completely address your concern.
String labelMessage = null;
String str = "asd";
try {
int x = Integer.parseInt(str);
labelMessage = //Whatever you want...
} catch (NumberFormatException e) {
e.printStackTrace();
labelMessage = "Error message = " + e.getMessage(); // OR some other menaingful message you want
}
//Set to you label field...
So I got this error in my program:
BankChargesWilson.java:55: error: variable checksCost might not have been initialized
System.out.println("Your total cost is " + money.format(checksCost) + ".");
^
1 error
But I don't understand why when I have the formatting object created and I initialized the checksCost variable earlier.
Heres the object + my definitions.
// Decimal Format Object
DecimalFormat money = new DecimalFormat("$##,###.##");
// Scanner Object for Input
Scanner keyboard = new Scanner (System.in);
// Variables
double baseFee = 10.00; // The base fee the bank requires for the account
double checkFee; // The fee for a check
int checksWritten; // The users inputted amount of checks written for the month
double checksCost; // The cost for the checks based on the amount written in the month
And heres my else-if statements where it's used, with the output and the spot thats causing an error.
if (checksWritten < 20)
{
checksCost = checksWritten * 0.10;
}
else if (checksWritten >= 20 && checksWritten <= 39)
{
checksCost = checksWritten * 0.08;
}
else if (checksWritten >= 40 && checksWritten <= 59)
{
checksCost = checksWritten * 0.06;
}
else if (checksWritten >= 60)
{
checksCost = checksWritten * 0.04;
}
System.out.println("You entered that you wrote " + checksWritten + " checks this month.");
System.out.println("Your total cost is " + money.format(checksCost) + ".");
I'm not sure why it's saying it's not initialized anymore.
Question though: Is the checksCost being seen in only the scope of my if-else-if loop? And if so, how come when it's defined further above?
Because the compiler doesn't analyze your code so deeply as you would imagine.
Although your if/else chain will execute a branch for sure according to its conditions, this outcome is not realized by the compiler which complains about the fact that you are missing an else condition.
You could solve the problem by initializing the variable or by letting last else if be a simple else (which wouldn't alter semantics in this specific case).
You need to provide a default initial value or you have to provide else block and provide your value there.
The reason is that, What happens all of your conditions failed to execute ??
When you provide a else block, then it is sure that always there is a chance to assign the value, either in if or in else
double checksCost;
if(){ //false
}
else if(){ //false
}
what is checksCost value now ??
Yes, your checksCost variable is only being see inside the block where it is initialized (in this case within the sections of the for loop).
The reason it can be seen inside the blocks of the if-else statement even though it has been declared above is because inner blocks can access code outside themselves but the reverse is not true.
You need to set an initial value for the checksCost variable. There could be a case where the value never gets set. There may be a situation where none of your conditional logic would be hit.
Java compiler requires that the variable must be initialized. At compile time, it doesn't check the logic of your code, so it thinks that there's a chance the variable will not be initialized if none of the "else if" match.
You need to initialize checkCost before the if/else part, or put an else { double = smth; } to end the if/else clause.
If checksWritten is equal to 0 what should checksCost equal? Initialize checksCost to that. Along the same lines you should probably initialize checksWritten to 0. Also don't leave off an else block ever because it leads to brittle code as you have just found out. So in this case just change the last else if to else.
I'm trying to build a basic weight calculator and came across "variable weightOut might not have been initialized" error. Google seems to indicate that this is because I need to initialize "weightOut" rather than just set it " = weightIn * .78 " . Is this true? Here is my code.
Scanner keyboard = new Scanner(System.in);
int weightIn, planetNumber;
double weightOut;
System.out.print("What is your weight? ");
weightIn = keyboard.nextInt();
System.out.println("I have information for the following planets: ");
System.out.println(" 1. Venus ");
...
System.out.print("What planet are you going to? ");
planetNumber = keyboard.nextInt();
if( planetNumber == 1 )
{
weightOut = weightIn * 0.78;
}
...
System.out.println("Your weight would be " + weightOut +
" on that planet.");
Local variables are not initialized with default values.Local variables should be initialized before use .
double weightOut = 0.0;
What if the if statement never really executed at run time ? The compiler is actually worried that in case during run time the local variable fails to get a value and you use it some where else , what value it should have given it doesn't have a default value !
In java method/local variables should be initialized. Uninitialized variables can give unexpected results and hence this is raised. In your code the value of weightOut will never be set if the enclosing if conditions is not met. You need to initialize the following variable with some default value:
int weightIn = 0;
int planetNumber = 0;
double weightOut = 0.0d;
What value will the the variable have if you don't enter the if-branch?
To fix this, add an else-branch at the end:
if (...)
myVar = x;
else if (...)
myVar = z;
else
myVar = y;
Setting the value in an else-branch rather than setting some default initial value not only makes the compiler happy but also prevents you from committing the error that the compiler is complaining about: if at some later point you add code that uses the variable before its correct value is set in the if statement you would still get an error message from the compiler and not an unexpected result when running the program.
You need to initialize "weightOut" to 0, because local variable can not be used without initializing.
As in your case you are assigning value in if condition and that one is not valid because in java value of local variable is decided at run time. That is the reason u are getting error.
What if the planet number is 0?
You should do:
double weightOut = 0;
I am rather new in Java and I can't seem to get around the error message
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:371)
at java.util.ArrayList.get(ArrayList.java:384)
at djurfarm.Animals.huntCatMouse(Animals.java:213)
at djurfarm.Djurfarm.main(Djurfarm.java:24)
Java Result: 1
I know what it means, that the index somewhere is below or above what it should be, but I can't for the life of me figure out why this is happening. Maybe it's because I've stared myself blind and won't see where the logic fails. Any help would be greatly appreciated. Here is the code for the method:
public void huntCatMouse() {
while (!CatList.isEmpty()) {
for (int i = 0 ; i < CatList.size(); i++) {
try {
TimeUnit.MILLISECONDS.sleep(500);
int slump = MouseList.size() - 1;
int num = CatList.size() - 1;
Cat CatRemover = CatList.get(num);
Mouse aMouse = MouseList.get(slump);
if (aMouse.getStrength().equals(false)) {
System.out.println("En katt fångar en mus.");
CatList.remove(CatRemover);
MouseList.remove(aMouse);
} else if (aMouse.getStrength().equals(true)) {
System.out.println("En mus lyckas fly från en katt.");
CatList.remove(CatRemover);
MouseList.remove(aMouse);
}
} catch (InterruptedException e) {
System.out.println("Fel i CatMouse");
}
if (MouseList.isEmpty()) {
System.out.println("Empty list");
break;
}
}
}
}
int slump = MouseList.size()-1;
It seems MouseList is a empty list and size method return 0 and slump become -1 and
MouseList.remove(aMouse); // MouseList.remove(-1)
causing ArrayIndexOutOfBoundsException at -1 index.
you have put condition !CatList.isEmpty(), It might be !CatList.isEmpty() && !MouseList.isEmpty()
The error may be because of this:
int slump = MouseList.size()-1;
int num = CatList.size()-1;
Cat CatRemover = CatList.get(num);
Mouse aMouse = MouseList.get(slump);
Here you are not checking whether MouseList or CatList size is greater than 0.
So if MouseList.size() returns 0,
so int slump = MouseList.size()-1; = int slump = -1;
Now when you do MouseList.get(slump); it means you are calling MouseList.get(-1);
So it throws that exception.
So first check whether the size of the list is greater than 0 (that is not empty).
As others have pointed out, the problem is that slump is -1 when you attempt to get(slump).
The reason it gets into that state is that you are not stopping when the mouse list becomes empty. In particular, the if (...) { break; } at the end only breaks out of the inner loop. So you try the condition for the outer loop, start the inner loop again and ... OOOPs!
The obvious fix would be to test both of the lists sizes in the outer loop's condition.
But a better fix would be to get rid of the inner loop entirely. You can implement this more simply with just one level of looping.
while (!CatList.isEmpty() && !MouseList.isEmpty()) {
try {
TimeUnit.MILLISECONDS.sleep(500);
int slump = MouseList.size() - 1;
int num = CatList.size() - 1;
Cat CatRemover = CatList.get(num);
Mouse aMouse = MouseList.get(slump);
if (aMouse.getStrength().equals(false)) {
System.out.println("En katt fångar en mus.");
CatList.remove(CatRemover);
MouseList.remove(aMouse);
} else if (aMouse.getStrength().equals(true)) {
System.out.println("En mus lyckas fly från en katt.");
CatList.remove(CatRemover);
MouseList.remove(aMouse);
}
} catch (InterruptedException e) {
System.out.println("Fel i CatMouse");
}
}
While I have your attention, you need to fix the names of your local variables. Java variable names should always start with a lowercase letter ... according to the Java style guide. And try to get the indentation right. It makes your code so much easier to read.
Finally, this is really peculiar: aMouse.getStrength().equals(true).
I would infer that getStrength() returns a boolean.
Assuming that, the simple way to test if it is true is simply aMouse.getStrength().
But "strength" is not a yes/no concept in English. It is something that you quantify.
But if "strength" really is a boolean, then the JavaBeans convention says that the method should be called isStrength() not getStrength().
I have a function that is recursively calling itself, and i want to detect and terminate if goes into an infinite loop, i.e - getting called for the same problem again. What is the easiest way to do that?
EDIT: This is the function, and it will get called recursively with different values of x and y. i want to terminate if in a recursive call, the value of the pair (x,y) is repeated.
int fromPos(int [] arr, int x, int y)
One way is to pass a depth variable from one call to the next, incrementing it each time your function calls itself. Check that depth doesn't grow larger than some particular threshold. Example:
int fromPos(int [] arr, int x, int y)
{
return fromPos(arr, x, y, 0);
}
int fromPos(int [] arr, int x, int y, int depth)
{
assert(depth < 10000);
// Do stuff
if (condition)
return fromPos(arr, x+1, y+1, depth + 1);
else
return 0;
}
If the function is purely functional, i.e. it has no state or side effects, then you could keep a Set of the arguments (edit: seeing your edit, you would keep a Set of pairs of (x,y) ) that it has been called with, and every time just check if the current argument is in the set. That way, you can detect a cycle if you run into it pretty quickly. But if the argument space is big and it takes a long time to get to a repeat, you may run out of your memory before you detect a cycle. In general, of course, you can't do it because this is the halting problem.
You will need to find a work-around, because as you've asked it, there is no general solution. See the Halting problem for more info.
An easy way would be to implement one of the following:
Pass the previous value and the new value to the recursive call and make your first step a check to see if they're the same - this is possibly your recursive case.
Pass a variable to indicate the number of times the function has been called, and arbitrarily limit the number of times it can be called.
You can only detect the most trivial ones using program analysis. The best you can do is to add guards in your particular circumstance and pass a depth level context. It is nearly impossible to detect the general case and differentiate legitimate use of recursive algorithms.
You can either use overloading for a consistent signature (this is the better method), or you can use a static variable:
int someFunc(int foo)
{
static recursionDepth = 0;
recursionDepth++;
if (recursionDepth > 10000)
{
recurisonDepth = 0;
return -1;
}
if (foo < 1000)
someFunc(foo + 3);
recursionDepth = 0;
return foo;
}
John Kugelman's answer with overloading is better beacuse it's thread safe, while static variables are not.
Billy3
Looks like you might be working on a 2D array. If you've got an extra bit to spare in the values of the array, you can use it as a flag. Check it, and terminate the recursion if the flag has been set. Then set it before continuing on.
If you don't have a bit to spare in the values, you can always make it an array of objects instead.
If you want to keep your method signature, you could keep a couple of sets to record old values of x and y.
static Set<Integer> xs;
static Set<Integer> ys;//Initialize this!
static int n=0;//keeps the count function calls.
int fromPos(int [] arr, int x, int y){
int newX= getX(x);
int newY= getY(y);
n++;
if ((!xs.add(Integer.valueOf(newX)) && !ys.add(Integer.valueOf(newY))){
assert(n<threshold); //threshold defined elsewhere.
fromPos(arr,newx,newy);
}
}
IMHO Only loops can go into an infinite loop.
If your method has too many level of recursion the JVM will throw a StackOverflowError. You can trap this error with a try/catch block and do whatever you plan to do when this condition occurs.
A recursive function terminates in case a condition is fulfilled.
Examples:
The result of a function is 0 or is 1
The maximum number of calls is reached
The result is lower/greater than the input value
In your case the condition is ([x0,y0] == [xN,yN]) OR ([x1,y1] == [xN,yN]) OR ([xN-1,yN-1] == [xN,yN])
0, 1, ...N are the indexes of the pairs
Thus you need a container(vector, list, map) to store all previous pairs and compare them to the current pair.
First use mvn findbugs:gui to open a gui which point to the line where this error is present.
I also faced the same problem and I solved it by adding a boolean variable in the loop verification.
Code before ->
for (local = 0; local < heightOfDiv; local = local + 200) { // Line under Error
tileInfo = appender.append(tileInfo).append(local).toString();
while (true) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
}
}
To Solve this problem, I just added a boolean variable and set it to false in the catch block. Check it down
for (local = 0; local < heightOfDiv; local = local + 200) {
tileInfo = appender.append(tileInfo).append(local).toString();
boolean terminationStatus = true;
while (terminationStatus) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
terminationStatus = false;
}
}
This is how i Solved this problem.
Hope this will help. :)