一、引言
当try里面有return,finally里面也有return时会有怎么的结果呢?
二、代码
话不多说,直接用代码进行测试。测试代码如下,
public class FinallyTest {
private static final FinallyTest instance = new FinallyTest("instance");
/**
* @param value
*/
private FinallyTest(String value) {
super();
this.value = value;
}
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
/**
* <p>测试基本类型
* @return
*/
public int testReturnInt() {
int b = 60;
try {
System.out.println("testReturnInt() in try. b = " + b);
// throw new NullPointerException();
return b += 50;
} catch (Exception e) {
System.out.println("testReturnInt() in catch. b = " + b);
// return b +=100;
}finally {
System.out.println("finally before edit. b = " +b);
b = 2000;
System.out.println("finally after edit. b= " + b);
return b;
}
// System.out.println("out of finally");
// return b + 1000;
}
/**
* <p>测试对象
* @return
*/
public FinallyTest testReturnObj() {
FinallyTest demo = new FinallyTest("origin");
try {
System.out.println("testReturnObj() in try. value = " + demo.getValue());
return demo;
} catch (Exception e) {
System.out.println("testReturnObj() in catch. value = " + demo.getValue());
} finally {
System.out.println("finally before edit. value = " + demo.getValue());
demo.setValue("modified");
System.out.println("finally after edit. value = " + demo.getValue());
return demo;
}
// System.out.println("out of finally");
// return demo;
}
public static void main(String[] args) {
System.out.println("in main. int =" + instance.testReturnInt()+"\n*************");
System.out.println("in main. value = " + instance.testReturnObj().getValue());
}
}
注意:上面这种return的方式(即在finally里面加上return),在eclipse里面会出现"finally block does not complete normally"的警告,下文会对此作一个说明。这里因为要举例,仍然暂时这么写。
三、测试用例
把try,catch,finally的情况分为三种:
1.try和finally型(即上文中的代码):
try{
return a = xxx;
}catch(Exception e){
xxx
}finally{
return a = xxxx;
}
终端输出:
testReturnInt() in try. b = 60
finally before edit. b = 110
finally after edit. b= 2000
in main. int =2000
*************
testReturnObj() in try. value = origin
finally before edit. value = origin
finally after edit. value = modified
in main. value = modified
结论:不论是基本类型还是引用对象,finally里面的return都会覆盖try里的return,这种方式不推荐。
2.catch和finally型:
try{
xxx;
}catch(Exception e){
return a = xxx;
}finally{
return a = xxxx;
}
相应地把testReturnInt()和testReturnObj()的return移动到catch里面,其他不变:
/**
* <p>测试基本类型
* @return
*/
public int testReturnInt() {
int b = 60;
try {
System.out.println("testReturnInt() in try. b = " + b);
// throw new NullPointerException();
// return b += 50;
// return b+50;
} catch (Exception e) {
System.out.println("testReturnInt() in catch. b = " + b);
return b +=50;
}finally {
System.out.println("finally before edit. b = " +b);
b = 2000;
System.out.println("finally after edit. b= " + b);
return b;
}
// System.out.println("out of finally");
// return b + 1000;
}
/**
* <p>测试对象
* @return
*/
public FinallyTest testReturnObj() {
FinallyTest demo = new FinallyTest("origin");
try {
System.out.println("testReturnObj() in try. value = " + demo.getValue());
// throw new NullPointerException();
// return demo;
} catch (Exception e) {
System.out.println("testReturnObj() in catch. value = " + demo.getValue());
return demo;
} finally {
System.out.println("finally before edit. value = " + demo.getValue());
demo.setValue("modified");
System.out.println("finally after edit. value = " + demo.getValue());
return demo;
}
// System.out.println("out of finally");
// return demo;
}
终端输出:
testReturnInt() in try. b = 60
finally before edit. b = 60
finally after edit. b= 2000
in main. int =2000
*************
testReturnObj() in try. value = origin
finally before edit. value = origin
finally after edit. value = modified
in main. value = modified
可以看到,由于没有异常,所以不会走catch分支,因此基本类型的值在finally before edit处不变,而引用对象的值由于是在finally里中set,因此仍然发生了变化。
如果把try中throw new NullPointerException();这句话的注释去掉,从而走catch分支,那么输出结果就和情况1是一样的。即基本类型的值在finally before edit处发生变化。
但从最终结果来看:不论是否发生异常,finally里面的return都是最终返回的值,即都会覆盖catch中的return。
3.try,catch,finally型
try{
xxx;
return a = xxx;
}catch(Exception e){
return a = xxx;
}finally{
return a = xxxx;
}
修改testReturnInt()和testReturnObj()如下:,通过传入不同的参数来决定是否走catch分支:
/**
* <p>
* 测试基本类型
*
* @return
*/
public int testReturnInt(int i) {
int b = 60;
try {
System.out.println("testReturnInt() in try. b = " + b);
if (i == -1) {
throw new NullPointerException();
} else {
return b += 50;
}
// return b+50;
} catch (Exception e) {
System.out.println("testReturnInt() in catch. b = " + b);
return b += 50;
} finally {
System.out.println("finally before edit. b = " + b);
b = 2000;
System.out.println("finally after edit. b= " + b);
return b;
}
// System.out.println("out of finally");
// return b + 1000;
}
这里基本上是对上述情况1和情况2的结合。不再给出具体的终端输出,结论仍然和情况1和情况2类似,即fianlly里面的return会对前面的return(不论是try还是catch分支进行覆盖)。
四、细心的同学应该会发现,其实我们还少了一种情况:
try{
xxx;
return a = xxx;
}catch(Exception e){
a=xxx;
}finally{
xxx;
a = xxxx;
}
System.out.println("out of finally");
a=xxx;
return a;
代码修改如下:
/**
* <p>
* 测试基本类型
*
* @return
*/
public int testReturnInt(int i) {
int b = 60;
try {
System.out.println("testReturnInt() in try. b = " + b);
if (i == -1) {
throw new NullPointerException();
}
return b += 50;
} catch (Exception e) {
System.out.println("testReturnInt() in catch. b = " + b);
// return b += 50;
} finally {
System.out.println("finally before edit. b = " + b);
b = 2000;
System.out.println("finally after edit. b= " + b);
// return b;
}
System.out.println("out of finally");
return b;
}
/**
* <p>
* 测试对象
*
* @return
*/
public FinallyTest testReturnObj(Object object) {
FinallyTest demo = new FinallyTest("origin");
try {
System.out.println("testReturnObj() in try. value = "
+ demo.getValue());
if (object == null) {
throw new NullPointerException();
}
return demo;
} catch (Exception e) {
System.out.println("testReturnObj() in catch. value = "
+ demo.getValue());
// return demo;
} finally {
System.out.println("finally before edit. value = "
+ demo.getValue());
demo.setValue("modified");
System.out
.println("finally after edit. value = " + demo.getValue());
// return demo;
}
System.out.println("out of finally");
demo.setValue("out of finally");
return demo;
}
public static void main(String[] args) {
System.out.println("in main. int =" + instance.testReturnInt(0)
+ "\n*************");
System.out.println("in main. value = "
+ instance.testReturnObj(new Object()).getValue());
}
终端输出:
testReturnInt() in try. b = 60
finally before edit. b = 110
finally after edit. b= 2000
in main. int =110
*************
testReturnObj() in try. value = origin
finally before edit. value = origin
finally after edit. value = modified
in main. value = modified
正常情况下会执行
try中的return,finally中的代码也会执行,但是finally外面的代码不会执行。
另外值得注意的是,基本类别的值在finally中发生了变化(对应输出中的:finally after edit. b= 2000),但是最终返回到main中的值仍然是try中的return
,即finally中的对基本类类型的修改是无效的(即对调用方是无效的);然而finally中对引用对象的修改却是有效的。
出现异常时会执行finally外面的return。这里不再作截图,读者有兴趣可以自行测试。
可见这种情况下a的值最多有可能在四个地方被改变,程序极易出现混乱,可读性很差,因此极其不推荐。
四、结论
终上,finally有return时,finally里面的return会覆盖原来的数据,而且也会修改原来的对象引用(基本类型数据不变----除非在finally之后有return语句)。所以,为了避免混乱,建议不要在finally里面写return。一般采用如下形式:
try{
xxx;
a=xxx;
return a;
}catch(Exception e){
xxx;
a=xxx;
return a;
}finally{
xxx;
}
或者统一在最后作return
try{
xxx;
a=xxx;
}catch(Exception e){
xxx;
a=xxx;
}finally{
xxx;
}
return a;
即finally里面不要作return(如非必要也尽量不要对返回的数据作修改),只作一些必要的关闭资源的工作。
分享到:
相关推荐
下面我们来详细讲解 try、catch、finally、return 执行顺序的规则和特点。 首先,我们需要了解 try、catch、finally 语句的基本用法。try 语句用于包装可能抛出异常的代码,catch 语句用于捕捉 try 语句中的异常,...
Java 中 finally 语句块与 return 的执行关系 Java 中的 finally 语句块是用于保证无论出现什么情况,一定要执行的代码块。...我们需要了解 finally 语句块的作用和执行顺序,以便编写正确和高效的 Java 代码。
在Java编程语言中,`finally`语句块是一个非常关键的结构,用于确保特定代码无论在...理解`finally`的执行顺序对于编写健壮的、易于维护的代码至关重要。在实际开发中,我们应该充分利用这一特性来提高代码的可靠性。
"Java中try finally return语句的执行顺序浅析" 关于Java中try finally return语句的执行顺序浅析是Java语言中一个重要的知识点,今天我们来探讨一下try finally return语句的执行顺序。 首先,需要了解的是...
try-catch-finally执行顺序验证(左边是.java文件,右边是.class文件) 提示: try、catch块内的return操作编译后会变成把return的值保存到变量var的操作。 总结: try、catch块内的return操作编译后会变成把return的值...
在编程语言中,异常处理是一种重要的错误处理机制,它允许我们优雅地捕获并处理运行时可能出现的问题。...理解这个执行顺序对于编写健壮的代码至关重要,特别是在处理资源管理和异常恢复的场景下。
2. **`return` 与 `finally` 的执行顺序**:在 `try` 块中遇到 `return` 时,会先执行 `finally` 语句块,然后再返回值。这是因为 `finally` 中的代码优先级高于 `return`,即使 `return` 已经被触发,`finally` ...
Java 中 finally 语句的执行顺序探讨 在 Java 中,finally 语句的执行顺序是一个常见的探讨话题。很多人都认为 finally 语句一定会被执行,但这是不正确的。在某些情况下,finally 语句可能不会被执行,例如在 try ...
总结来说,Python 中的 `try`、`except` 和 `finally` 执行顺序如下: 1. 先执行 `try` 块。 2. 如果在 `try` 块中发生异常,执行与之匹配的 `except` 块。 3. 不管是否发生异常,都会执行 `finally` 块。 4. 如果 `...
在Java中,finally语句可以与return语句结合使用,但是它们的执行顺序是非常重要的。finally语句是在try的return语句执行之后,return返回之前执行的。这意味着,如果在try块中执行了return语句,finally语句将在...
在涉及`return`语句时,其执行顺序可能会引起混淆,尤其是在`finally`块中有操作的情况下。让我们深入探讨一下这个面试题以及相关的知识点。 首先,`finally`块的特性是它总是在`try`或`catch`块执行完毕后执行,...
以下是一个简单的例子来展示`finally`块的执行顺序: ```java public class FinallyTest { public static void main(String[] args) { int r = test(); System.out.println(r); } public static int test() { ...
- 示例 `T2` 中,`try` 里的 `return` 使得 `catch` 和 `finally` 之后的代码不被执行,但 `finally` 还是会执行。 - 示例 `Mine` 展示了文件操作异常的处理。当文件不存在时,`FileInputStream` 构造函数会抛出 `...
描述中的“Sequência de exercícios em Java”进一步确认了这是关于Java编程中的执行顺序问题,这通常涉及到程序控制流的概念,如顺序执行、条件判断和循环。 在Java中,程序的执行顺序遵循一定的规则: 1. **源...
- 如果`try`块和`finally`块都有`return`语句,`finally`块的`return`会覆盖`try`块的`return`。这是因为在`return`语句执行后,返回值会被保存,然后`finally`块的代码执行,最后函数真正返回。如: ```java ...
8. try-catch-finally执行顺序:当try块中的return语句执行时,finally块的代码会在return之前执行。因此,选项C正确。 9. 异常处理和返回值:在try-catch-finally结构中,finally块的return语句总是最后执行,所以...
即使在`try`或`catch`块中有`return`语句,`finally`块的代码也会被执行。 ```csharp finally { // 无论是否发生异常都会执行的代码 } ``` 在示例中,无论`j`的值是否为0,`finally`块的`Console.WriteLine(j....
#### 五、try-catch-finally 的执行顺序 1. **正常执行**:如果`try` 块内的代码正常执行完毕(没有抛出异常),则执行`finally` 块。 2. **异常发生**:如果`try` 块内的代码抛出了异常,并且有对应的`catch` 块...
通过以上分析,我们可以看到使用`CountDownLatch`来协调多线程执行顺序是一种非常有效的方式。这种方式不仅能够简化程序设计,还能够提高系统的稳定性和健壮性。在实际项目开发中,合理地利用这种技术可以有效地解决...