如何让 Java 识别在 try 块中声明的变量



我正在做一个加密项目,我大部分时间都在工作。 我正在从文件中读取明文并对其进行加密,然后将其写入另一个文本文件。 我对解密也有同样的事情。 我有这个工作,但我对读取和写入文件的尝试和捕获方法有点困惑。我在一种方法中有两个尝试和捕获,第二个尝试方法无法识别我的"解密"变量。 我应该如何处理?这是我的代码:

public static void decrypt(String pathname)
{
  File file = new File(pathname);
  Scanner input = null;
  try
  {
     input = new Scanner(file);
     String tempEncrypted = input.nextLine();
     StringBuffer encrypted = new StringBuffer(tempEncrypted);
     StringBuffer decrypted = new StringBuffer("");
     int shiftAmount = (int)encrypted.charAt(0);
     for(int i = 1; i < encrypted.length(); i++)
     {
        int decChar = ((int)encrypted.charAt(i) - shiftAmount);
        while((int)decChar < 32)
        {
           decChar+=95;
        }
        decrypted.append((char)decChar);
     }
  }
  catch(FileNotFoundException ex)
  {
     System.out.println("*** Cannot open " + pathname + " ***");
     System.exit(1);
  }
  try {
     BufferedWriter out = new BufferedWriter(new FileWriter("decrypted.txt"));
     for(int j = 0; j < decrypted.length(); j++)
     {
        out.write(decrypted.charAt(j));
     }
     out.close();
  } 
  catch (IOException e) {}

}

谢谢,任何帮助将不胜感激。

你错过了尝试/捕获块的重点。 如果引发异常,则发生错误。 您不希望从失败的 try 块中检索信息

相反,只需将您的 try 块组合成一个 try/catch,如下所示:

public static void decrypt(String pathname)
{
  File file = new File(pathname);
  Scanner input = null;
  try
  {
     input = new Scanner(file);
     String tempEncrypted = input.nextLine();
     StringBuffer encrypted = new StringBuffer(tempEncrypted);
     StringBuffer decrypted = new StringBuffer("");
     int shiftAmount = (int)encrypted.charAt(0);
     for(int i = 1; i < encrypted.length(); i++)
     {
        int decChar = ((int)encrypted.charAt(i) - shiftAmount);
        while((int)decChar < 32)
        {
           decChar+=95;
        }
        decrypted.append((char)decChar);
     }
    BufferedWriter out = new BufferedWriter(new FileWriter("decrypted.txt"));
    for(int j = 0; j < decrypted.length(); j++)
    {
       out.write(decrypted.charAt(j));
    }
    out.close();
  }
  catch(FileNotFoundException ex)
  {
     System.out.println("*** Cannot open " + pathname + " ***");
     System.exit(1);
  }
  catch (IOException e) {}
}

这是变量范围的问题。第二个 try/catch 块与第一个块中创建的任何变量无关。一旦第一个 try/catch 块完成,变量就会丢失。

如果需要该变量在第二个变量中可见,则必须在第一次尝试之前对其进行初始化,然后在 try 块中设置值。这有意义吗?

decrypted变量超出了第二个try的范围。要使其在那里可见,您可以声明它并在第一个try块之外对其进行初始化,在该块中声明Scanner对象和file

File file = new File(pathname);
Scanner input = null;
StringBuffer decrypted = new StringBuffer("");
...

如果你有

void myMethod() {
    try {
        SomeClass x = someValue;
    }
    catch(..) {..}
    SomeClass y = x;
}

编译器会(正确地)抱怨x没有在最终赋值语句中定义,因为x是在try{}括号内声明的,并且声明无法"逃脱"{}定义的"范围"。

如果你有

void myMethod() {
    SomeClass x;
    try {
        x = someValue;
    }
    catch(..) {..}
    SomeClass y = x;
}

编译器现在将抱怨 x 的值未在最终赋值语句中设置。 这是因为无法保证执行try范围内的语句。 (如果你用if (some condition)替换try,并且没有在else腿上设置x,情况也是如此。

但如果你有

void myMethod() {
    SomeClass x = null;
    try {
        x = someValue;
    }
    catch(..) {..}
    SomeClass y = x;
}

编译器会(合理地)高兴,因为x在最终赋值语句的范围内是"可见的",并且还知道它沿着从它的声明点到使用它的位置的所有可能路径分配了一个值。

如果在代码块中声明变量,则其范围仅限于该块。您在 try/catch 块内声明decrypted,因此在块之外,decrypted不再可用。您可以通过将 try/catch 块前面的decrypted声明移动到 try/catch 块前面并仅保留在分配内部来解决此问题。

StringBuffer encrypted = new StringBuffer();
StringBuffer decrypted = new StringBuffer();
try {
 input = new Scanner(file);
 String tempEncrypted = input.nextLine();
 encrypted = new StringBuffer(tempEncrypted);
 decrypted = new StringBuffer("");
 int shiftAmount = (int)encrypted.charAt(0);
 ...

最新更新