【问题标题】:Try Catch and Finally with Return Statements [duplicate]使用 Return 语句尝试 Catch 和 finally [重复]
【发布时间】:2014-04-19 22:43:11
【问题描述】:

在准备 Java 认证时,我看到了一些这样棘手的代码。

这里最后的返回值是:10,但是最后被调用,它把returnval修改为20。

有人可以解释为什么会这样吗?是因为 catch 的 returnval 范围不同吗?还是我在这里遗漏了什么。

class MultipleReturn {
int getInt() {
int returnVal = 10;
try {
     String[] students = {"Harry", "Paul"};
     System.out.println(students[5]);
    }
catch (Exception e) {
    System.out.println("About to return :" + returnVal);
    return returnVal;
    }
finally {
    returnVal += 10;
    System.out.println("Return value is now :" + returnVal);
    }
return returnVal;
}

public static void main(String args[]) {
       MultipleReturn var = new MultipleReturn();
       System.out.println("In Main:" + var.getInt());
      }
}

另一个后续代码是:

class MultipleReturn {
  StringBuilder getStringBuilder() {
  StringBuilder returnVal = new StringBuilder("10");
  try {
      String[] students = {"Harry", "Paul"};
      System.out.println(students[5]);
  }
  catch (Exception e) {
      System.out.println("About to return :" + returnVal);
      return returnVal;
  }
  finally {
     returnVal.append("10");
     System.out.println("Return value is now :" + returnVal);
  }
  return returnVal;
  }

  public static void main(String args[]) {
    MultipleReturn var = new MultipleReturn();
    System.out.println("In Main:" + var.getStringBuilder());
  }
}

这里的输出是 1010,这是有意义的,因为 finally 修改了 returnval 并且它被持久化了。

任何解释都会有所帮助。

我确实理解这是写得很糟糕的代码,任何头脑正常的人都不应该写这样的东西。

【问题讨论】:

    标签: java return try-catch finally


    【解决方案1】:

    在第一个示例中,finally 没有改变任何内容,因为 10 已被标记为要在 catch 语句中返回的值。如果您将return 添加到finally 块或从catch 中删除return 并仅保留最后一个return 语句,那么您将获得值20。最重要的是您在这里只返回值而不是引用。

    另一方面,在第二个示例中,StringBuilder 是可变的,returnVal 是对对象的引用。值“10”的 returnVal 被标记为要返回的值,但在您打印 main 方法 finally 块内的 returnVal 值之前,它会将 returnVal 的值从“10”更改为“1010”。如果您在 main 方法中打印 returnVal,您将获得该对象的最新值,即“1010”。之所以这样工作,是因为 getStringBuilder 返回可变的 StringBuilder 的引用。

    【讨论】:

    • 我没有想到这一面。感谢您指出这一点。
    【解决方案2】:

    这里发生了很多事情,但我认为归结为,在 getStringBuilder 版本中,returnVal 对象是可变的,并且同一个对象在 finally 子句中发生了变异,如您观察到的那样返回“1010”。另一方面,当您将 10 加到 finally 子句中的内存地址与返回值不同的整数时,将返回不同的值。

    尝试运行以下代码以更好地说明。

    class MultipleReturn {
      int getInt() {
        int returnVal = 10;
    
        System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
        try {
          String[] students = { "Harry", "Paul" };
          System.out.println(students[5]);
        } catch (Exception e) {
          System.out.println("About to return :" + returnVal);
          System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
          return returnVal;
        } finally {
          returnVal += 10;
          System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
          System.out.println("Return value is now :" + returnVal);
        }
        return returnVal;
      }
    
      StringBuilder getStringBuilder() {
        StringBuilder returnVal = new StringBuilder("10");
    
        System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
        try {
          String[] students = { "Harry", "Paul" };
          System.out.println(students[5]);
        } catch (Exception e) {
          System.out.println("About to return :" + returnVal);
          System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
          return returnVal;
        } finally {
          returnVal.append("10");
          System.out.println("Return value is now :" + returnVal);
          System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
        }
        return returnVal;
      }
    
    
      static class MutableInteger {
        public int val;
    
        @Override
        public String toString() {
          return Integer.toString(val);
        }
      }
    
    
      MutableInteger getMutableInt() {
        MutableInteger returnVal = new MutableInteger();
        returnVal.val = 10;
        System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
        System.out.println(System.identityHashCode(returnVal));
        try {
          String[] students = { "Harry", "Paul" };
          System.out.println(students[5]);
        } catch (Exception e) {
          System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
          System.out.println("About to return :" + returnVal);
          return returnVal;
        } finally {
          returnVal.val += 10;
          System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
          System.out.println("Return value is now :" + returnVal);
        }
        return returnVal;
      }  
    
      public static void main(String args[]) {
        MultipleReturn var = new MultipleReturn();
        System.out.println("In Main:" + var.getInt());
        System.out.println();
        System.out.println("In Main:" + var.getStringBuilder());
        System.out.println();
        System.out.println(var.getMutableInt());
      }
    }
    

    结果:

    returnVal 的身份哈希:1152321476 即将返回:10 catch 块中 returnVal 的标识哈希:1152321476 最终返回值的身份哈希:2116610996 返回值现在是:20 在主要:10

    returnVal 的身份哈希:814397217 即将返回:10 catch 块中 returnVal 的标识哈希:814397217 返回值现在是:1010 最终返回值的身份哈希:814397217 主要:1010

    returnVal 的身份哈希:1660743788 1660743788 catch 块中 returnVal 的标识哈希:1660743788 即将返回:10 最终返回值的身份哈希:1660743788 返回值现在是:20 20

    【讨论】:

    • 这让事情变得更加清晰。谢谢
    猜你喜欢
    • 2010-11-25
    • 2011-08-07
    • 2019-07-06
    • 2013-02-19
    • 2014-05-11
    • 2016-10-07
    • 2014-06-05
    • 2020-06-17
    相关资源
    最近更新 更多