Variable in for loop is giving a message that "The value of the local variable i is not used" - java

I wrote a for loop that is supposed to determine if there is user input. If there is, it sets the 6 elements of int[] valueArr to the input, a vararg int[] statValue. If there is no input, it sets all elements equal to -1.
if (statValue.length == 6) {
for (int i = 0; i < 6; i++) {
valueArr[i] = statValue[i];
}
} else {
for (int i : valueArr) {
i = -1;
}
}
I am using Visual Studio Code, and it is giving me a message in for (int i : valueArr) :
"The value of the local variable i is not used."
That particular for loop syntax is still new to me, so I may be very well blind, but it was working in another file:
for(int i : rollResults) {
sum = sum + i;
}
I feel that I should also mention that the for loop giving me trouble is in a private void method. I'm still fairly new and just recently started using private methods. I noticed the method would give the same message when not used elsewhere, but I do not see why it would appear here.
I tried closing and reopening Visual Studio Code, deleting and retyping the code, and other forms of that. In my short experience, I've had times where I received errors and messages that should not be there and fixed them with what I mentioned, but none of that worked here.

for (int i : valueArr) {
.... CODE HERE ...
}
This sets up a loop which will run CODE HERE a certain number of times. Inside this loop, at the start of every loop, an entirely new variable is created named i, containing one of the values in valueArr. Once the loop ends this variable is destroyed. Notably, i is not directly the value in valueArr - modifying it does nothing - other than affect this one loop if you use i later in within the block. It does not modify the contents of valueArr.
Hence why you get the warning: i = -1 does nothing - you change what i is, and then the loop ends, which means i goes away and your code hasn't changed anything or done anything, which surely you didn't intend. Hence, warning.
It's not entirely clear what you want to do here. If you intend to set all values in valueArr to -1, you want:
for (int i = 0; i < valueArr.length; i++) valueArr[i] = -1;
Or, actually, you can do that more simply:
Arrays.fill(valueArr, -1);
valueArr[i] = -1 changes the value of the i-th value in the valueArr array to -1. for (int i : valueArr) i = -1; does nothing.

Related

Returning value from method and "The Value Assigned Is Never Used" [duplicate]

This question already has answers here:
What does the "Assigned value is never used" warning mean?
(5 answers)
Closed 3 months ago.
I'm following Princeton's introductory computer science course (I'm not a student, just teaching myself). I working on this assignment.
Main is calling two methods: amplify and reverse, both of which return an array. Amplify multiplies all values in the array by a constant alpha. Reverse returns an array that lists the original array values in reverse order, ex. {1,2,3} -> {3,2,1}.
Amplify works fine, but nothing happens when I call reverse and I get a bug that states: The Value Assigned Is Never Used
public class audiocollage {
// Returns a new array that rescales a[] by a factor of alpha.
public static double[] amplify(double[] a, double alpha) {
for (int i = 0; i < a.length; i++) {
a[i] = a[i] * alpha;
}
return a;
}
// Returns a new array that is the reverse of a[].
public static double[] reverse(double[] a) {
double[] b = new double[a.length];
for (int i = a.length - 1, j = 0; i >= 0; i--, j++) {
b[j] = a[i];
}
return b;
}
// Creates an audio collage and plays it on standard audio.
public static void main(String[] args) {
double[] samples = StdAudio.read("cow.wav");
double alpha = 2.0;
samples = amplify(samples, alpha);
samples = reverse(samples);
}
}
It sounds like you have two questions:
Why doesn't anything happen when I call reverse(samples)?
The code you're showing does nothing with the result of reverse(samples) other than store it in the variable samples (overwriting its previous value). You will need to do something with samples after that to observe the new array (like printing samples, which should now appear to be reversed).
Which leads into the next question:
Why do I get a warning about "the value assigned to samples is never used"?
This is a warning saying that the code you wrote doesn't do anything.
Dead store to local variable is the first line of the warning, which describes what's happening: the value stored to samples is "dead" -- it is never used again, and so we may as well have skipped that line altogether. That causes your compiler (or extension) to give us a warning because it's almost certain that the code you wrote is not doing what you intended, so in many cases that warning can be helpful for spotting mistakes.
This warning can be resolved by using samples somehow, such as by printing it, calling another function with it, etc.
The previous line
samples = amplify(samples, alpha);
doesn't generate that warning because it's output is used in the following call to reverse():
samples = reverse(samples);
// ^ usage of `samples` variable!
This is made even clearer by using different variables for all your arrays:
public static void main(String[] args) {
// No warning; samplesRaw used later
double[] samplesRaw = StdAudio.read("cow.wav");
double alpha = 2.0;
// No warning; samplesAmplified used later
samplesAmplified = amplify(samplesRaw, alpha);
// WARNING! samplesReversed is never used!
samplesReversed = reverse(samplesAmplified);
}
If the hint is related to the last line, it means you have a local variables samples which has not used ( you assigned a value but never read it)

Processing multidimensional array

Hey I can't get processing to run my code due to a NullPointerException on my array value in the println statement.
for (bx=0; bx<=7; bx++) {
for (by=0; by<=4; by++) {
rect(bx*BRICK_WIDTH, by*BRICK_HEIGHT, BRICK_WIDTH, BRICK_HEIGHT);
int[][] a = {{bx}, {by}};
}
println (a[bx][by]);
}
From just the code you posted, I wouldn't expect you to get a NullPointerException. I would expect you to get a The variable "a" does not exist error.
So I'm guessing that you have another a variable at the top of your sketch, like this:
int[][] a;
void draw(){
for (bx=0; bx<=7; bx++) {
for (by=0; by<=4; by++) {
rect(bx*BRICK_WIDTH, by*BRICK_HEIGHT, BRICK_WIDTH, BRICK_HEIGHT);
int[][] a = {{bx}, {by}};
}
println (a[bx][by]);
}
}
Please note that this is why it's so important for you to post a MCVE, so we don't have to guess at what your code is doing.
If this is the case, your problem is caused because the int[][] a = {{bx}, {by}}; line inside the for loop is declaring a different variable with the same name. It's not touching the skethc-level a variable. So the sketch-level a variable still has the default value of null, hence the NullPointerException when you try to use it.
Also note that it doesn't make a ton of sense to assign a to anything inside the for loop. To see why, consider this simpler example:
int x = 0;
for(int i = 0; i < 10; i++){
x = i;
}
println(x);
You'll see that the x variable only "keeps" the last value we assigned to it. The same thing is true of arrays. Maybe you meant to set a particular index of your array?
If you're still having trouble then please post a MCVE. Good luck.

Error in Eclipse Luna 'Variable is not initialized' when declared outside of For loop and initialized within it

When using Eclipse Luna I run into this issue: When I declare a variable outside of the for loop (or another structure), then initialize it within the For loop, upon closing the for loop the value assigned to the variable within the for loop is not carried over.
Perhaps this is how it's supposed to be, but when using Eclipse Juno I don't have this problem.
int sebastian;
for(int i=0;i<8;i++)
{
sebastian = 5*i;
System.out.println(sebastian);
}
I'm not sure what's wrong there, but it SHOULD be carried over. It looks like it carries over, and when I run it, it carries over.
I ran
public static void main(String[] args) {
int sebastian = 0;
for (int i = 0; i < 8; i++) {
sebastian = 5 * i;
System.out.println(sebastian);
}
// this should print the last value a second time
System.out.println(sebastian);
}
and my output was
0
5
10
15
20
25
30
35
35 // this is the carry over that shows up
See rules for 'Definite Assignment' in the Java Language Spec. You can't refer to a local variable before it has a value assigned:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html
Local variables do not have default values. When you write int sebastian; in a method, the variable sebastien does not the value 0, rather it is unassigned. You cannot use the variable until it is "definitely assigned". The rules for definite assignment are complicated. It seems clear that the variable will have been given a value in the loop (because the loop repeats 8 times), but that does not meet the rules for definite assignment.
int sebastian;
for(int i=0;i<8;i++)
{
sebastian = 5*i;
System.out.println(sebastian); // sebastien is definitely assigned here. It was assigned the line before!
}
System.out.println(sebastian); // sebastien is not definitely assigned here.
The easiest way round this to just give the variable a "dummy" value when you declare it:
int sebastien = -1;

Why this for statement shows Dead code in Java?

In this class, I defined a constructor that initializes an array and fill it with Point2D.Double. I want to define a toString method that outputs the Point2D.Double in the array. So inside the toString method, I make a for loop that returns every Point2D.Double in the array. The problem is, I don't know why Eclipse tells me that the update in the for statement is dead code.
import java.awt.geom.Point2D;
public class SimplePolygon {
public int n; // number of vertices of the polygon
public Point2D.Double[] vertices; // vertices[0..n-1] around the polygon
// boundary
public SimplePolygon(int size) {
n = size;
vertices = new Point2D.Double[n]; // creates array with n size. Elements are doubles.
for(int i = 0; i < n; i++)
{
Point2D.Double point = new Point2D.Double(Math.random() * 6, Math.random() * 6);
vertices[i] = point;
}
}
public String toString() {
for(int i = 0 ; i < n ; i++)
{
return "" + vertices[i];
}
return "";
}
I too was puzzled by this. (And the other answers!) So I cut-and-pasted it into Eclipse to see what it actually says.
And what Eclipse is actually says is that i++ is unreachable in this line.
for(int i = 0 ; i < n ; i++)
And in fact, that is correct! If you ever enter the loop body, the body will unconditionally return. Hence the i++ can never be executed.
Note also that this is a warning not an error. This code is not invalid according to the JLS rules about unreachability.
You are right to be puzzled by the other explanations. The final return statement is reachable. Consider the case where the class is instantiated with a negative value for n (or size). In that case, the for loop body will never be executed, and control will go to the final return.
However, their suggestions as to how to fix the problem are correct. You should not have a return in the loop body.
The problem is because of the return statement in the for loop. Remember, whenever you use return, you immediately end the method and stop running any code. That means that your toString method will loop exactly only once, returning only vertices[0]. The second return below the loop never has a chance to execute, so is considered dead code.
This is actually incorrect! See Stephan's answer for a better/accurate explanation of what's going on.
Regardless, you still need to fix your code. Instead of returning something inside the loop, you probably want to combine the values and return them all at once at the very end. An easy way to do this might be:
public String toString() {
String output = "";
for(int i = 0 ; i < n ; i++)
{
output += vertices[i] + " ";
}
return output;
}
Now, instead of returning immediately, we're accumulating values in the loop and returning at the very end.
(Note that the code here isn't very efficient -- you'd probably want to use something like String.join or StringBuilder instead, but if you're a beginner, this works for now)

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