JREN
JREN

Reputation: 3630

Variables in different switch cases can't have the same name?

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?

Upvotes: 7

Views: 10755

Answers (6)

AllTooSir
AllTooSir

Reputation: 49362

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:

  1. Define an explicit block under each case using { .. }, though it looks pretty odd I must say.

    OR

  2. In each case you can delegate the logic to a method call .

Upvotes: 12

Sanjaya Liyanage
Sanjaya Liyanage

Reputation: 4746

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.

Upvotes: 4

Boris the Spider
Boris the Spider

Reputation: 61128

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);
}

Upvotes: 2

Steve P.
Steve P.

Reputation: 14699

case in switch statements are not blocks; hence, by declaring the same variable in multiple switch cases, you're attempting to redefine the variable. This works in if statements because they form blocks.

Either declare them before the switch, or put blocks in your cases.

Upvotes: 0

morpheus05
morpheus05

Reputation: 4872

You can use curly brackets {} after the case:

int aInt = 3;
switch (aInt) {
  case 0:  {
    String text = "";
    break;
  }
  case 1: {
    String text = "";
    break;
  }
}

Upvotes: 3

yushulx
yushulx

Reputation: 12140

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;
}

Upvotes: 13

Related Questions