Java try/catch 方法

Java try/catch method

我是 Java 的新手,我的函数有很多 try/catch 块我想清理。我想把每个部分都放在一个单独的私有辅助方法中,并且只调用主函数中的几个函数,但是当我这样做时,我得到了一个 java.util.NoSuchElementException 扫描仪。

这里是原函数。任何帮助将不胜感激。

 public void playGame(List<Card> deck, FreecellOperations<Card> model, int numCascades,
                   int numOpens, boolean shuffle) {
try {
  Scanner scan = new Scanner(rd);

try {
  Objects.requireNonNull(model);
  Objects.requireNonNull(deck);
} catch (NullPointerException npe) {
  throw new IllegalArgumentException("Cannot start game with null parameters.");
}

try {
  model.startGame(deck, numCascades, numOpens, shuffle);
 } catch (IllegalArgumentException iae) {
  ap.append("Could not start game. " + iae.getMessage());
  return;
 }

  ap.append(model.getGameState() + "\n");
  while (!model.isGameOver()) {
    String source = scan.next();
    if (source.substring(0, 1).equals("q") || source.substring(0, 1).equals("Q")) {
      ap.append("Game quit prematurely.");
      return;
    }
    String cardIndex = scan.next();
    if (cardIndex.substring(0, 1).equals("q") || cardIndex.substring(0, 1).equals("Q")) {
      ap.append("Game quit prematurely.");
      return;
    }
    String destination = scan.next();
    if (destination.substring(0, 1).equals("q") || destination.substring(0, 1).equals("Q")) {
      ap.append("Game quit prematurely.");
      return;
    }

    int pileNumber = 0;
    PileType sourceType = null;
    boolean isValidSource = false;
    while (!isValidSource) {
      try {
        switch (source.charAt(0)) {
          case 'F':
            sourceType = PileType.FOUNDATION;
            pileNumber = this.validMoveCheck(source, 4);
            isValidSource = true;
            break;
          case 'O':
            sourceType = PileType.OPEN;
            pileNumber = this.validMoveCheck(source, numOpens);
            isValidSource = true;
            break;
          case 'C':
            sourceType = PileType.CASCADE;
            pileNumber = this.validMoveCheck(source, numCascades);
            isValidSource = true;
            break;
          default:
            throw new IllegalArgumentException();
        }
      } catch (IllegalArgumentException iae) {
        ap.append("Invalid source pile. Try again.\n");
        source = scan.next();
        if (source.equals("q") || source.equals("Q")) {
          ap.append("Game quit prematurely.");
          return;
        }
      }
    }
    int cardNum = 0;
    boolean isValidCard = false;
    while (!isValidCard) {
      try {
        cardNum = Integer.parseInt(cardIndex);
        isValidCard = true;
      } catch (NumberFormatException nfe) {
        ap.append("Invalid card number. Try again.\n");
        cardIndex = scan.next();
        if (cardIndex.equals("Q") || cardIndex.equals("q")) {
          ap.append("Game quit prematurely.");
          return;
        }
      }
    }

    PileType destType = null;
    int destPileNum = 0;
    boolean isValidDest = false;
    while (!isValidDest) {
      try {
        switch (destination.charAt(0)) {
          case 'F':
            destType = PileType.FOUNDATION;
            destPileNum = this.validMoveCheck(destination, 4);
            isValidDest = true;
            break;
          case 'C':
            destType = PileType.CASCADE;
            destPileNum = this.validMoveCheck(destination, numCascades);
            isValidDest = true;
            break;
          case 'O':
            destType = PileType.OPEN;
            destPileNum = this.validMoveCheck(destination, 4);
            isValidDest = true;
            break;
          default:
            throw new IllegalArgumentException();
        }
      } catch (IllegalArgumentException iae) {
        ap.append("Invalid destination pile. Try again.\n");
        destination = scan.next();
        if (destination.equals("q") || destination.equals("Q")) {
          ap.append("Game quit prematurely.");
          return;
        }
      }
    }
    try {
      model.move(sourceType, (pileNumber - 1), (cardNum - 1), destType, (destPileNum - 1));
      ap.append(model.getGameState() + "\n");
    } catch (IllegalArgumentException iae) {
      ap.append("Invalid move. Try again. " + iae.getMessage() + "\n");
    }
  }
  ap.append("Game over.");
} catch (IOException ioe) {
  return;
}
}

首先,为了不得到 java.util.NoSuchElementException,您需要使用 hasNextLine()检查下一行是否存在。 在您的 while 循环中添加该检查:

while (!model.isGameOver() && scan.hasNextLine()) {
...
}

其次,您在此处的其他评论中获得了很好的代码样式提示,我建议您采纳它们:)

几点评论:

首先,您可以用简单的 if 语句替换很多 try/catch 块(或完全消除它们)。

例如:

default:
        throw new IllegalArgumentException();
    }
  } catch (IllegalArgumentException iae) {
    ap.append("Invalid destination pile. Try again.\n");
    destination = scan.next();
    if (destination.equals("q") || destination.equals("Q")) {
      ap.append("Game quit prematurely.");
      return;
    }
  }

为什么不直接做:

default:
    ap.append("Invalid destination pile. Try again.\n");
    destination = scan.next();
    if (destination.equals("q") || destination.equals("Q")) {
      ap.append("Game quit prematurely.");
      return;
    }
   break;

或者类似的东西?为什么要为例外烦恼?

另外,这个逻辑是错误的:

cardNum = Integer.parseInt(cardIndex);
isValidCard = true;

它是一个整数并不能证明它是一张有效的卡片。如果有人输入 5,321 怎么办?显然, 一张 int,但它不是一张真正的卡片。另外,请参阅 here(及其副本)以了解封装它的方法。