1

出于学习目的,我正在玩弄例外,我有一个问题。请看下面的代码:

public static void main(String[] args) {

    System.out.print(getNumber());

}


public static double getNumber() {

    double number =10;

    try {
        String [] students = {"nick","george"};
        System.out.println(students[5]);
    }
    catch (ArrayIndexOutOfBoundsException ex ) {
        System.out.println("In catch block "+ number);
        return number;
    }
    finally {
        number +=10;
        System.out.println("The value is now "+ number);
    }
    System.out.println("hiiiii");
    return number;
}

为什么在这种情况下 main 方法的输出将是 10,为什么如果我运行相同的示例并返回一个对象,值会改变?

public static void main(String[] args) {
    System.out.println("In main  is "+getStringBuffer());
}



public static StringBuffer getStringBuffer() {

    StringBuffer number = new StringBuffer("10");

    try {
        String [] names= {"george" ,"nick"};
        System.out.println(names[5]);
    }

    catch (ArrayIndexOutOfBoundsException ex1) {
        System.out.println("In catch block "+ number);
        return number;
    }

    finally {
    number.reverse();   
        System.out.println("In finally is "+ number);
    }
    System.out.println("hiiii");
    return number;
}
4

4 回答 4

3

因为在第一个示例中,您正在返回一个原语,并且它的返回值已经在堆栈上,并且不能被 finally 块更改。

在第二个示例中,您将返回一个引用变量,并且它指向的值可以由 finally 块更改。

于 2013-11-10T19:01:37.553 回答
3

该方法返回的值设置为return它遇到的语句。所以

return number;

并不意味着“记住你要返回number变量”,它的意思是“评估number变量,并记住结果值以将其用作返回值”。number稍后(在块中)更改变量的内容对finally方法返回的值没有影响,这已经确定。

我们怎么知道呢?因为return必须评估表达式(根据JLS 的第 14.17 节)。例如,假设你有

return number + 5;

...你不会期望得到25,因为你有10,点击return语句,然后10finally块中添加另一个,然后表达式添加5更多,对吗?return计算表达式并记住该作为方法的返回值。

在您给出的对象示例中,块中没有更改返回的值。finally它仍然只是对对象的引用。您正在更改正在返回其引用的对象的状态,但引用并未被更改。如果你换了

number.reverse();

number = new StringBuffer();

...你会看到你得到与 a 完全相同的行为double,因为在这种情况下,你正在更改保存在(对对象的引用)中的number,就像你对number += 10;.

于 2013-11-10T19:01:52.363 回答
2

catch块在块之前运行finally。在原始版本的代码中,当return发生时,该变量的值仍然是 10,所以这就是返回的值。

在代码的第二个版本中,您将返回 a StringBuffer,但您正在编辑该 的内容StringBuffer。因此,虽然只有一个StringBuffer,您要返回,但当调用方法看到返回的对象时,它已经被更新了。

另一种看待这一点的方式是,在第二种情况下,返回的东西是对位于堆中的对象的引用;但在第一种情况下,您实际上返回的是一个值,而不是引用。

于 2013-11-10T18:59:36.230 回答
0

第一个问题:为什么在这种情况下 main 方法的输出是 10。

因为您试图访问不可用的值。

原因:String [] students = {"nick","george"};

herestudents 数组大小为 2,您正在尝试访问第 5 个元素,如下所示:

  System.out.println(students[5]);  

通过调用上面的语句 java throws ArrayIndexOutOfBoundsException

当您捕获ArrayIndexOutOfBoundsException异常时,将执行 catch 块内的所有语句。

在这里,您正在打印数字值,如下所示:

System.out.println("In catch block "+ number); 

这将打印数字10.

于 2013-11-10T18:55:31.187 回答