【问题标题】:Variables in different switch cases can't have the same name?不同switch case中的变量不能同名?
【发布时间】:2013-07-10 16:22:38
【问题描述】:

我正在重构一些代码以使其更易于阅读,我遇到了一些我觉得很奇怪的东西,我想知道是否有人可以向我解释一下。

原始代码:

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

重构后:

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

乍一看这看起来完全合理,但这给了我一个语法错误。

链接所有引用以进行本地重命名(不更改其他文件中的引用)

事实证明,由于某种原因,在 switch 语句中,我无法在不同的情况下再次使用 String idString value

这让我的变量命名相当尴尬。

现在您可以说:“只需在 switch 语句上方声明变量即可。”但这意味着我总是创建我的变量,即使tokensLeft 既不是 3 也不是 2 并且我不需要我的变量。感觉就像在使用不必要的内存。

谁能向我解释一下为什么 switch case 会这样以及我该如何解决我的问题?

【问题讨论】:

  • 使用方法 - 无论如何这是一个好习惯,你的范围会为你排序。如果您真的想编写意大利面条式代码,请使用显式块 ({})。

标签: java variables switch-statement syntax-error


【解决方案1】:

您正在重新定义变量,即重复变量声明。 case 不会阻塞。

根据JLS 14

块是一系列语句、局部类声明和大括号内的局部变量声明。

你有两个选择:

  1. 使用{ .. }在每种情况下定义一个显式块,尽管它 我必须说看起来很奇怪。

  2. 在每个case 中,您可以将逻辑委托给方法调用。

【讨论】:

  • 但这如何帮助我解决问题?
  • 您可以在每个案例的方法调用中包含逻辑?
【解决方案2】:

添加 {}。试试这个:

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

【讨论】:

  • 非常聪明。这应该是正确的答案。它实现了 op 的目标,即在多个 switch case 中使用相同的变量名。
【解决方案3】:

按照下面的方法做

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

这里不会像你说的那样引起内存问题。 当它执行该方法时,它会将 id 和 value 保留在堆栈中,并且在堆中没有这些引用的相关对象。因此,内存没有问题,而是两个参考所需的小内存。

【讨论】:

    【解决方案4】:

    你可以在大小写之后使用大括号{}:

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

    【讨论】:

      【解决方案5】:

      根本不声明变量怎么样?

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

      我为Integer.parseInt 添加了static 导入。

      最好在switch 中用命名良好的方法调用您的逻辑并声明您想要的任何变量:

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

      【讨论】:

      • 我想它会起作用,但是当我最初的目标是让它更容易时,它似乎让事情变得不那么容易阅读。
      • 在这种情况下创建方法。您的代码不易阅读 - 最佳实践(和 Bob 大叔)建议方法的长度不应超过 10 行。这个开关块已经快20了。
      • 您对如何区分我创建的两种方法有什么建议,因为唯一的区别是其中一种将使用第三个参数。除此之外,它们是相同的。并且这些方法都只接受 1 个参数 tokens
      【解决方案6】:

      switch 语句中的case 不是blocks;因此,通过在多个 switch 案例中声明相同的变量,您正在尝试重新定义该变量。这适用于if 语句,因为它们形成blocks

      要么在切换之前声明它们,要么在你的情况下放置块。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-08
        • 2013-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多