有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我是编程新手,一直试图通过编写一个简单的程序来学习Java的基础知识,该程序将对某些文本应用Caesar变换。我已经能够做到这一点,到目前为止,我的代码所做的是:

  1. 询问用户希望文本移动多少单位
  2. 提示用户输入一些文本
  3. 应用Caesar移位的单位数并打印结果

以下是工作代码:

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

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

我遇到的问题是代码(如下)似乎完全忽略了我的try块。我认为这是因为我的try块包含声明整数“shift”的行,当我向下滚动到代码中实际使用“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);
    }
    }

那么,为什么这一小小的变化突然阻止了“转变”的宣布呢


共 (4) 个答案

  1. # 1 楼答案

    变量仅限于其声明的范围。有关更多信息,请参见this nice little tutorial about variable scope in Java(如果您想了解技术,请参见JLS section 6.3,在您的案例中,以“局部变量声明的范围”开头的行是相关的)

    作用域的最简单解释是它们在其中声明的{ ... }

    就你而言:

    ...
    try {
        int shift = sc.nextInt();
    } ...
    

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

    int shift;
    
    try {
        shift = sc.nextInt();
    } catch (...) {
        ...
    }
    

    nextInt()引发异常的代码路径仍然可以保持shift未初始化。在这种情况下,要解决这个问题,一个选项是对其进行初始化:

    int shift = 0;
    
    try {
        shift = sc.nextInt();
    } catch (...) {
        ...
    }
    

    另一个选项是确保即使引发异常也能获得值:

    int shift;
    
    try {
        shift = sc.nextInt();
    } catch (...) {
        shift = 0;
        ...
    }
    

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

    int shift;
    
    try {
        shift = sc.nextInt();
    } catch (Exception x) {
        throw x;
    }
    
    // shift can never be used uninitialized here
    

    第四个选项是以这样的方式构造代码,即shifttry块之外不需要shift

    try {
        int shift = sc.nextInt();
        // do everything that needs to be done with shift here
    } catch (...) {
        ...
    }
    
    // shift is unneeded here
    
  2. # 2 楼答案

    在Java中,每当你在一个块中声明一个变量时,你就是在对这个变量进行我们所说的局部声明。这意味着该变量只能在声明它的块中看到。在本例中,由于您在try块内声明了shift,因此从try块外的任何地方都看不到它。要解决这个问题,只需在try块之外声明它,如下所示:

    int shift;
    try {
        shift = sc.nextInt();
    }
    ...
    

    您可以在这里了解有关Java中声明范围的更多信息:https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.3

  3. # 3 楼答案

    在区块外声明移位。问题的出现是因为移位的作用域仅限于try。将其更改为:

    int shift=0;
    try {
        shift = sc.nextInt();
    }
    
  4. # 4 楼答案

    问题是,当您在try块中声明变量时,该变量的作用域就是try块。一旦try块完成执行,try块中声明的所有变量都将被删除。您需要将声明移到try块之外。像这样:

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

    希望这有帮助:)