修改finally块中方法的返回值不会返回实际修改的值

时间:2013-10-14 12:49:31

标签: java

作为一项规则,无论finally块或trycontinue或{{1}是否抛出异常,始终会执行breakreturn块中的语句遇到。

因此,下面给出的代码片段中方法的返回值应该改变,但不会改变。

try

在调用此方法之前,方法final class Product { private String productName=null; public Product(String productName) { this.productName=productName; } public String getProductName() { try { return this.productName; } finally { this.productName="The product name has been modified in the finally block."; System.out.println("Product name in the finally block : "+this.productName); } } } public final class Test { public static void main(String...args) { System.out.println(new Product("Intel core i3").getProductName()); } } 只返回构造函数指定给字段getProductName()的产品名称。

在此方法返回之前,productName块中的值productName被修改。因此,该方法应返回此新修改的值,但它返回在构造此类的实例时分配给finally的初始值。


它产生以下输出:

  

finally块中的产品名称:产品名称已在finally块中修改   英特尔酷睿i3

为什么此方法不返回分配给productName块中productName字段的新值?它应该返回新值。不应该吗?

2 个答案:

答案 0 :(得分:5)

这里的关键是您从方法返回相应对象的引用值。在调用者方面,你得到的是方法参考的副本。请记住,Java中的所有内容都是按值传递的。甚至引用都是按值传递的。

使用finally块中的引用修改对象时,更改将在调用方可见。但是,如果您更改reference本身的值,那么更改当然不会反映在调用者方面,因为现在它们都有不同的引用。

  

在此方法返回之前,将在finally块中修改productName的值。

您在finally区块中所执行的操作是,您已为String引用分配了新的productName对象。这将改变productName的参考值。因此,根据上面的段落,更改不会反映在呼叫者端。它们都处理2个不同的String对象。

  

因此,该方法应返回此新修改值。

不,不应该。因为两个String对象都是不同的。使用StringBuilder对象尝试此代码:

public StringBuilder getProductName() {

    StringBuilder sb = new StringBuilder(productName);
    try {
        return sb;
    }
    finally {
        sb.append("Modified");
    }
}

现在StringBuilder的更改将反映在返回值中。那么这里发生了什么?

首先使用以下return语句:

return sb;

您返回了对您创建的StringBuilder对象的引用。然后在finally块中:

sb.append("Modified");

..你修改了sb指向的对象。由于您没有更改sb本身的引用值,因此对于指向该对象的所有引用,对象的更改都是可见的,因此调用方的结尾也是如此。

现在将finally块修改为:

sb = new StringBuilder("Modified");

并查看是否反映了更改。您不会看到任何回报值的变化。因为,现在您已经更改了sb本身的参考值。

此外,如果从finally块返回修改后的引用,则原始返回值将被覆盖。尝试将finally块修改为:

finally {

    this.productName="The product name has been modified in the finally block.";
    System.out.println("Product name in the finally block : "+this.productName);

    return this.productName;  // Note: This is bad idea
}

现在您将看到新值。


另见:

答案 1 :(得分:1)

因为finally块没有执行return this.productName

try块中的return this.productName返回对象的地址。 finally块中的赋值创建一个新对象,保持返回值不变。