try块中的代码被忽略,为什么?

0 java try-catch

我是编程新手,并且一直在尝试通过编写一个将Caesar转换应用于某些文本的简单程序来学习Java的基础知识.我已经能够做到这一点,到目前为止我的代码是这样的:

  1. 询问用户他们想要移动文本的单位数.
  2. 提示用户输入一些文本.
  3. 按照许多单位应用凯撒移位并打印结果.

这是工作代码:

import java.util.Scanner;
class Shift{

public static void main(String[] args){

    //This will scan for user input.
    Scanner sc = new Scanner(System.in);
    System.out.print("Shift by this many characters (0-25): ");
    int shift = sc.nextInt();
    sc.nextLine();//Skips over the whitespace after the integer
    System.out.print("Enter Text: ");
    String input = sc.nextLine();
    sc.close();

    //Initialise a character array containing every letter in the alphabet. 
    char[] alphabetArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m',
                            'n','o','p','q','r','s','t','u','v','w','x','y','z'};
    char[] alphabetArrayCaps = {'A','B','C','D','E','F','G','H','I','J','K','L','M',
                                'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

    //Initialise the two variables that will be used in the next step.
    char[] constantArray = input.toCharArray();
    char[] output = input.toCharArray();

    //Implement a Caesar shift by the given number of units.
    for (int i=0; i < constantArray.length; i++){ //cycles through the user input character by character
        for (int j=0; j <= 25; j++){ //cycles through the alphabet
            if (constantArray[i] == alphabetArray[j]){
                    output[i] = alphabetArray[(j+shift)%26];
            }
            else if (constantArray[i] == alphabetArrayCaps[j]){
                        output[i] = alphabetArrayCaps[(j+shift)%26];
            }
        }
    }
    System.out.println(output);
    }
    }
Run Code Online (Sandbox Code Playgroud)

此代码的问题在于,当要求用户输入整数时,如果输入任何其他内容,则会出现异常.我认为这将是一个学习处理异常的好地方,并且已经参考了本指南如何使用try-catch块来实现此目的.

我遇到的问题是代码(下面)似乎完全忽略了我的try块.我认为这是因为我的try块包含声明整数"shift"的行,当我向下滚动到我的代码中实际使用"shift"的地方时,我得到一个警告说"转换不能解决为变量"并且无法编译.

这是导致问题的代码,唯一的区别是我在try块中包含了一行,并在它之后添加了一个应该打印错误消息的catch块(虽然我还没有编译代码但是还没有没有机会玩这个,看看它到底做了什么.

import java.util.Scanner;
class Shift{

public static void main(String[] args){

    //This will scan for user input.
    Scanner sc = new Scanner(System.in);
    System.out.print("Shift by this many characters (0-25): ");

    try {
        int shift = sc.nextInt();
    }
    catch (java.util.InputMismatchException e){
        System.err.println("InputMismatchException: " + e.getMessage());                        
    }

    sc.nextLine();//Skips over the whitespace after the integer
    System.out.print("Enter Text: ");
    String input = sc.nextLine();
    sc.close();

    //Initialise a character array containing every letter in the alphabet. 
    char[] alphabetArray = {'a','b','c','d','e','f','g','h','i','j','k','l','m',
                            'n','o','p','q','r','s','t','u','v','w','x','y','z'};
    char[] alphabetArrayCaps = {'A','B','C','D','E','F','G','H','I','J','K','L','M',
                                'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

    //Initialise the two variables that will be used in the next step.
    char[] constantArray = input.toCharArray();
    char[] output = input.toCharArray();

    //Implement a Caesar shift by the given number of units.
    for (int i=0; i < constantArray.length; i++){ //cycles through the user input character by character
        for (int j=0; j <= 25; j++){ //cycles through the alphabet
            if (constantArray[i] == alphabetArray[j]){
                    output[i] = alphabetArray[(j+shift)%26];
            }
            else if (constantArray[i] == alphabetArrayCaps[j]){
                        output[i] = alphabetArrayCaps[(j+shift)%26];
            }
        }
    }
    System.out.println(output);
    }
    }
Run Code Online (Sandbox Code Playgroud)

那么为什么这一小小的变化突然停止被宣布"转变"?

Jas*_*n C 6

变量仅限于它们声明的范围.有关更多信息,请参阅这个关于Java中变量作用域的小教程(或者如果您想获得技术,请参阅JLS第6.3节,在您的情况下,以"局部变量声明"是相关的".

范围的最简单解释是{ ... }它们被声明的对.

在你的情况下:

...
try {
    int shift = sc.nextInt();
} ...
Run Code Online (Sandbox Code Playgroud)

该变量shift在{ ... }该try块之外是不可见的.您必须在更高的范围内声明它,例如作为方法的局部变量.但是,在try块的情况下,如果您只是将声明移到外面,您仍然会遇到"变量可能被使用未初始化"的警告,因为在此:

int shift;

try {
    shift = sc.nextInt();
} catch (...) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

nextInt()抛出异常的代码路径仍然可以保持shift未初始化状态.要在这种情况下解决这个问题,一个选项就是初始化它:

int shift = 0;

try {
    shift = sc.nextInt();
} catch (...) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是确保即使抛出异常它也会得到一个值:

int shift;

try {
    shift = sc.nextInt();
} catch (...) {
    shift = 0;
    ...
}
Run Code Online (Sandbox Code Playgroud)

第三种选择是以shift一种在抛出异常时从不尝试使用的方式构造代码,尽管这不适合您的示例(但是,为了完整性):

int shift;

try {
    shift = sc.nextInt();
} catch (Exception x) {
    throw x;
}

// shift can never be used uninitialized here
Run Code Online (Sandbox Code Playgroud)

第四个选项是以块shift外部不需要的方式构造代码try:

try {
    int shift = sc.nextInt();
    // do everything that needs to be done with shift here
} catch (...) {
    ...
}

// shift is unneeded here
Run Code Online (Sandbox Code Playgroud)