finally语句的执行有一定前提,需执行到try语句。如果在try语句之前就返回,finally语句必然不会执行。此外,在执行try语句过程中,终止JVM也不会执行finally语句。所以,在finally语句块执行的前提下,讨论finally语句到底在return之前还是之后呢? 在这里分了以下几种情况来分析:
1.情况1,就是try中的return语句先执行但并没有立即返回,其次finally块中的语句执行,最后try中return返回。
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int num = 10;
try {
System.out.println("try doing...");
return num += 10;
}catch (Exception e){
System.out.println("catch doing...");
}finally {
System.out.println("finally doing...");
if (num > 15){
System.out.println("num > 15, num = " + num);
}
}
return 100; //不可达
}
}
运行结果:
try doing...
finally doing...
num > 15, num = 20
20
其过程是,try中的return语句num += 10先执行,num = 20,但该return语句没有将结果直接返回,而是执行finally语句块的语句,打印“finally doing…”,以及if语句打印“num > 15, num = 20”,执行完finally块内容。最后,return返回try中的结果。(在此说下,Java中到底是传值还是传址?详情见)
2.情况2,finally中的return语句会覆盖try中return的结果
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int num = 10;
try {
System.out.println("try doing...");
return num += 10;
}catch (Exception e){
System.out.println("catch doing...");
}finally {
System.out.println("finally doing...");
if (num > 15){
System.out.println("num > 15, num = " + num);
}
return 30;
}
}
}
运行结果:
try doing...
finally doing...
num > 15, num = 20
30
其过程是,try中的return语句num += 10依旧先执行,num = 20,该return语句没有将结果直接返回,继续执行finally语句块的语句,打印“finally doing…”,以及if语句打印“num > 15, num = 20”,后执行finally中的return语句并将30作为结果返回,从而造成了try中返回的结果num=20被覆盖。
3.情况3,如果finally语句中没有return语句覆盖返回值,那么原来的返回值是否会改变?
其实这与Java参数传递方式是相似的(均为值传递),“返回值”均不会改变,这里的“返回值”有两层含义。
如果返回的是基本数据类型,没有return语句覆盖返回值时,原来的返回值不会改变。注意,此处的返回值指的是 try语句块 中变量num所指向的存储单元的内容。(num = 20,返回的是20)。
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int num = 10;
try {
System.out.println("try doing...");
return num += 10; //返回的是num所对应存储单元的内容,即20
}catch (Exception e){
System.out.println("catch doing...");
}finally {
System.out.println("finally doing...");
if (num > 15){
System.out.println("num > 15, num = " + num);
}
num = 100;
System.out.println(num);
}
return 0;
}
}
运行结果:
try doing...
finally doing...
num > 15, num = 20
100
20
返回的是引用数据类型,没有return语句覆盖返回值时,原来的返回值也不会改变。注意,此处的返回值指的是 try语句块中 引用变量sb所指向的存储单元的内容,内容是对象的地址值。
public class Test {
public static void main(String[] args) {
System.out.println(test().toString()); //4. 访问的是0x0001所指的对象
}
public static StringBuffer test(){
StringBuffer sb = new StringBuffer("Kyrie");//1. 假设0x0001是创建的对象地址值
try {
System.out.println("try doing...");
return sb; //2. sb->0x0001,返回的是sb所对应存储单元的内容,即0x0001
}catch (Exception e){
System.out.println("catch doing...");
}finally {
System.out.println("finally doing...");
sb.append("2011");
sb = new StringBuffer("6666"); //3. 此处,相当于sb指向了一个新对象,新对象的地址值为0x1000,那么sb所指存储单元内容为0x1000
System.out.println(sb.toString());
}
return null;
}
}
运行结果:
try doing...
finally doing...
6666
Kyrie2011
4.情况4,try块里的return语句在异常的情况下不会被执行
public class Test{
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int num = 10;
try {
System.out.println("doing try。。。");
num = num / 0;
return num += 100; //不会被执行
}catch (Exception e){
num += 10;
System.out.println("doing catch, num = " + num);
}finally {
if (num > 15){
System.out.println(" num > 15, num = " + num);
}
}
return -1;
}
}
运行结果:
doing try。。。
doing catch, num = 20
num > 15, num = 20
-1
从上述结果可看出,try中发生的异常时,try中的return语句不会被执行。
5.情况5,当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int num = 10;
try {
System.out.println("doing try。。。");
num = num / 0;
return num += 100;
}catch (Exception e){
System.out.println("doing catch, num = " + num);
return num += 40; //先执行 num+=40,此时num所指向的存储单元的内容为40
}finally {
if (num > 15){
System.out.println(" num > 15, num = " + num);
}
num += 1000;
}
}
}
运行结果:
doing try。。。
doing catch, num = 10
num > 15, num = 50
50
过程是发生异常后,catch中的return语句先执行,确定了返回值后再去执行finally块,执行完后catch中的return再返回结果,finally里对num的改变对返回值无影响,原因同前面一样,也就是说情况与try中的return语句执行完全一样。