作为一项规则,无论finally
块或try
,continue
或{{1}是否抛出异常,始终会执行break
块return
块中的语句遇到。
因此,下面给出的代码片段中方法的返回值应该改变,但不会改变。
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
字段的新值?它应该返回新值。不应该吗?
答案 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块中的赋值创建一个新对象,保持返回值不变。