I was refactoring some code to make it easier to read and I ran into something that I find weird and I was wondering if anyone could explain this to me.
Original code:
if(tokensLeft == 3) {
String id = tokens.nextToken();
String value = tokens.nextToken();
String trailerId = tokens.nextToken();
rawListener.binaryInfo(id, Integer.parseInt(value), trailerId, this);
} else if(tokensLeft == 2) {
String id = tokens.nextToken();
String value = tokens.nextToken();
rawListener.binaryInfo(id, Integer.parseInt(value), this);
} else {
System.out.println("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
}
After refactoring:
switch(tokensLeft) {
case 3:
String id = tokens.nextToken();
String value = tokens.nextToken();
String trailerId = tokens.nextToken();
rawListener.binaryInfo(id, Integer.parseInt(value), trailerId, this);
break;
case 2:
String id = tokens.nextToken(); // Syntax error
String value = tokens.nextToken(); // Syntax error
rawListener.binaryInfo(id, Integer.parseInt(value), this);
break;
default:
System.out.println("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
break;
}
At first glance this looks perfectly reasonable, but this gives me a syntax error.
Link all references for a local rename (does not change references in other files)
It turns out that for some reason in a switch statement, I am unable to use the String id
and String value
again in a different case.
This makes naming my variables rather awkward.
Now you could say: "Just declare your variables above your switch statement." But that would mean that I always create my variables, even if tokensLeft
is neither 3 or 2 and I wouldn't need my variables. That just feels like using unnecessary memory.
Can anyone explain to me why the switch case does this and how I could solve my problem?
Yes, if they are not in the same lexical scope. For example (we have two variables named x , one is the formal int x , and another is the double x in the inside block).
The switch/case statement in the c language is defined by the language specification to use an int value, so you can not use a float value. The value of the 'expression' in a switch-case statement must be an integer, char, short, long. Float and double are not allowed.
The switch statement can include any number of case instances. However, no two constant-expression values within the same switch statement can have the same value.
Variables belonging to different functions in a single code can have same name if we declare that variable globally as shown in the following code snippet below .
add {}. try this:
switch(tokensLeft) {
case 3:
{
String id = tokens.nextToken();
String value = tokens.nextToken();
String trailerId = tokens.nextToken();
rawListener.binaryInfo(id, Integer.parseInt(value), trailerId, this);
}
break;
case 2:
{
String id = tokens.nextToken(); // Syntax error
String value = tokens.nextToken(); // Syntax error
rawListener.binaryInfo(id, Integer.parseInt(value), this);
}
break;
default:
System.out.println("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
break;
}
You are redefining variables , that is duplicate variable declaration . case
doesn't make a block.
As per JLS 14:
A block is a sequence of statements, local class declarations and local variable declaration statements within braces.
You have two options here:
Define an explicit block under each case using { .. }
, though it
looks pretty odd I must say.
OR
In each case
you can delegate the logic to a method call .
Do it as below
String id;
String value ;
switch(tokensLeft) {
case 3:
id = tokens.nextToken();
value = tokens.nextToken();
String trailerId = tokens.nextToken();
rawListener.binaryInfo(id, Integer.parseInt(value), trailerId, this);
break;
case 2:
id = tokens.nextToken(); // Syntax error
value = tokens.nextToken(); // Syntax error
rawListener.binaryInfo(id, Integer.parseInt(value), this);
break;
default:
System.out.println("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
break;
}
Here it will not cause memory issues as you say. When it executes the method it will keep id and value in the stack and no relevant object in heap for those references. Thus no issue with memory instead the small memory it take for two ref.
You can use curly brackets {} after the case:
int aInt = 3;
switch (aInt) {
case 0: {
String text = "";
break;
}
case 1: {
String text = "";
break;
}
}
How about not declaring the variables at all?
switch (tokensLeft) {
case 3:
rawListener.binaryInfo(
tokens.nextToken(),
parseInt(tokens.nextToken()),
tokens.nextToken(),
this);
break;
case 2:
rawListener.binaryInfo(
tokens.nextToken(),
parseInt(tokens.nextToken()),
this);
break;
default:
throw new IllegalArgumentException("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
}
I added a static
import for Integer.parseInt
.
Better yet call your logic in well named methods from the switch
and declare whatever variables you want:
public void parseTokens() {
switch (tokensLeft) {
case 3:
parseThreeTokens(rawListener, tokens);
break;
case 2:
parseTwoTokens(rawListener, tokens);
break;
default:
throw new IllegalArgumentException("Method call binaryInfo could not be done because: \"Wrong number of parameters\"");
}
}
public void parseThreeTokens(final RawListener rawListener, final Tokens tokens) {
final String id = tokens.nextToken();
final String value = tokens.nextToken();
final String trailerId = tokens.nextToken();
rawListener.binaryInfo(id, parseInt(value), trailerId, this);
}
public void parseTwoTokens(final RawListener rawListener, final Tokens tokens) {
final String id = tokens.nextToken();
final String value = tokens.nextToken();
rawListener.binaryInfo(id, parseInt(value), this);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With