首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解“最后”块

理解“最后”块
EN

Stack Overflow用户
提问于 2010-07-12 05:38:31
回答 6查看 1.1K关注 0票数 5

为了理解finally块的行为,我编写了七个测试用例。finally如何工作背后的逻辑是什么?

代码语言:javascript
运行
复制
package core;

public class Test {
    public static void main(String[] args) {
        new Test().testFinally();
    }

    public void testFinally() {
        System.out.println("One = " + tryOne());
        System.out.println("Two = " + tryTwo());
        System.out.println("Three = " + tryThree());
        System.out.println("Four = " + tryFour());
        System.out.println("Five = " + tryFive());
        System.out.println("Six = " + trySix());
        System.out.println("Seven = " + trySeven());
    }

    protected StringBuilder tryOne() {
        StringBuilder builder = new StringBuilder();
        try {
            builder.append("Cool");
            return builder.append("Return");
        }
        finally {
            builder = null;
        }
    }

    protected String tryTwo() {
        String builder = "Cool";
        try {
            return builder += "Return";
        }
        finally {
            builder = null;
        }
    }

    protected int tryThree() {
        int builder = 99;
        try {
            return builder += 1;
        }
        finally {
            builder = 0;
        }
    }

    protected StringBuilder tryFour() {
        StringBuilder builder = new StringBuilder();
        try {
            builder.append("Cool");
            return builder.append("Return");
        }
        finally {
            builder.append("+1");
        }
    }

    protected int tryFive() {
        int count = 0;
        try {
            count = 99;
        }
        finally {
            count++;
        }
        return count;
    }

    protected int trySix() {
        int count = 0;
        try {
            count = 99;
        }
        finally {
            count = 1;
        }
        return count;
    }

    protected int trySeven() {
        int count = 0;
        try {
            count = 99;
            return count;
        }
        finally {
            count++;
        }
    }
}

为什么builder = null不能工作?

为什么builder.append("+1")工作,而count++(在trySeven()中)不工作?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-07-12 05:45:23

完成返回后,重写的唯一方法是执行另一个返回(正如在从Java中的最后一个块返回中讨论的,这几乎总是一个糟糕的主意),或者以其他方式突然完成。你的测试永远不会从最终结果中回来。

JLS§14.1定义了突然完成。突然完成的类型之一是返回。由于返回,在1、2、3、4和7中的try块突然完成。正如§14.20.2所解释的那样,如果try块由于抛出之外的原因R而突然完成,那么最终块将立即执行。

如果最终块正常完成(这意味着不返回,除其他外),“try语句由于R.突然完成”。换句话说,try启动的返回保持不变;这适用于所有测试。如果您从finally返回,“try语句由于原因S(和原因R被丢弃)突然完成。”(这是新的压倒一切的回报)。

所以在tryOne中,如果你这样做的话:

代码语言:javascript
运行
复制
finally {
            builder = null;
            return builder;
        }

这个新的返回S将覆盖原始返回R。

对于builder.append("+1") in tryFour,请记住StringBuilder是可变的,因此仍然要返回对try中指定的相同对象的引用。你只是在做最后一分钟的变异。

tryFivetrySix是直进的.由于try中没有返回,try和finally都正常完成,并且它执行的方式就像没有try一样--最终。

票数 10
EN

Stack Overflow用户

发布于 2010-07-12 05:52:26

让我们从用例开始,您将更经常地看到-您有一个资源,您必须关闭以避免泄漏。

代码语言:javascript
运行
复制
public void deleteRows(Connection conn) throws SQLException {
    Statement statement = conn.createStatement();
    try {
        statement.execute("DELETE * FROM foo");
    } finally {
        statement.close();
    }
}

在这种情况下,我们必须在完成时关闭语句,这样就不会泄漏数据库资源。这将确保在异常被抛出时,我们将始终在函数退出之前关闭我们的语句。

尝试{.}最后的{.}块是为了确保某些东西在方法终止时总是会执行。对于异常情况,它是最有用的。如果你发现自己在做这样的事情:

代码语言:javascript
运行
复制
public String thisShouldBeRefactored(List<String> foo) {
    try { 
        if(foo == null) {
            return null;
        } else if(foo.length == 1) {
            return foo.get(0);
        } else {
            return foo.get(1);
        }
    } finally {
        System.out.println("Exiting function!");
    }
}

你没有真正正确地使用。这是一种对性能的惩罚。当你有你必须清理的异常情况时,坚持使用它。请尝试将上面的内容重构到以下内容:

代码语言:javascript
运行
复制
public String thisShouldBeRefactored(List<String> foo) {
    final String result;

    if(foo == null) {
        result = null;
    } else if(foo.length == 1) {
        result = foo.get(0);
    } else {
        result = foo.get(1);
    }

    System.out.println("Exiting function!");

    return result;
}
票数 2
EN

Stack Overflow用户

发布于 2010-07-12 06:22:52

当您离开try块时,将执行finally块。“返回”语句做两件事,一是它设置函数的返回值,二是它退出该函数。通常,这看起来像一个原子操作,但是在try块中,它将导致在设置返回值之后和函数退出之前执行finally块。

返回执行:

  1. 赋值
  2. 最后运行块
  3. 退出函数

示例一(原语):

代码语言:javascript
运行
复制
int count = 1;//Assign local primitive count to 1
try{
  return count; //Assign primitive return value to count (1)
}finally{
  count++ //Updates count but not return value
}

例2(参考):

代码语言:javascript
运行
复制
StringBuilder sb = new StringBuilder();//Assign sb a new StringBuilder
try{
    return sb;//return a reference to StringBuilder
}finally{
    sb.append("hello");//modifies the returned StringBuilder
}

例三(参考):

代码语言:javascript
运行
复制
   StringBuilder sb = new StringBuilder();//Assign sb a new StringBuilder
   try{
      return sb;//return a reference to StringBuilder
   }finally{
      sb = null;//Update local reference sb not return value
   }

示例四(返回):

代码语言:javascript
运行
复制
   int count = 1;   //assign count
   try{
      return count; //return current value of count (1)
   }finally{
      count++;      //update count to two but not return value
      return count; //return current value of count (2) 
                    //replaces old return value and exits the finally block
   }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3226100

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档