public class Test {
     
    public int inc() {
        int x;
        try {
            x = 1;
            return x;
        } catch (Exception e) {
            x = 2;
            return x;
        } finally {
            x = 3;
        }
    }
     
    public StringBuffer inc(StringBuffer x) {
        try {
            x.append("1");
            x = new StringBuffer();// 如果在里面加参数例如这样new StringBuffer("5")结果就变了
            return x;
        } catch (Exception e) {
            x.append("2");
            return x;
        } finally {
            x.append("3");
            x = new StringBuffer("4");
              //这后面加return x;也会变
        }
    }
     
    public static void main(String[] args) {
        int x = new Test().inc();
        System.out.println(x);
        StringBuffer x1 = new StringBuffer(),x2 = new Test().inc(x1);
        System.out.println(x1);
        System.out.println(x2);
    }
}问:new StringBuffer();是否是重新开辟了一块内存,在这单中x1,和x2的指向是否有变化?stringbuffer

解决方案 »

  1.   

    StringBuffer 内存地址是可变的
    String 内存地址是不变的
      

  2.   

      StringBuffer x1 = new StringBuffer(),x2 = new Test().inc(x1);
            System.out.println(x1);
            System.out.println(x2);
    这要是折后面三个语句的问题,x1传入后执行 x.append("1");
    那x1就是1,之后执行这一句
                x = new StringBuffer();
    那么是说x1已经更改了引用了啊?指向了空,可为什么还是1.
    // 如果在里面加参数例如这样new StringBuffer("5")结果就变了
    输出的x2变为了53了。
       
      

  3.   

    1、StringBuffer 第一次new 都会生成新的引用。因为x是形参变量,所以不会对原有地址里面的数据发生更改。
    2、finally 关键字是在运行try里面的return 语句后才会被执行的,其实x = new StringBuffer("4");  x的值已经被更改了,但是因为try里面的return已经把值返回给主调程序,所以就算更改了也无法返回数值。
      

  4.   


    第一处这里只是x更该了引用x1 并没;
    第2处new StringBuffer("5")时x引用的对象是值是5,然后return x,返回的是这时候x引用的对象,在通过finally里的x.append("3")使其引用的对象值变为了"53",所以这样的结果
      

  5.   

    执行x2 = new Test().inc(x1);这句话时,对传入的x1进行了 x.append("1");操作x1该内存地址的对象值变为1;之后,变量x指向发生变化,指向新地址,并将新地址对象进行返回:
    x = new StringBuffer();
    return x;对于新对象,在finally里进行了 x.append("3");的操作,使inc(x1)返回的是3的对象,之后变量x又指向新地址,这个地址没什么用了这个东西一看还真比较晕乎,debug一下思路会清晰一些的。
      

  6.   

    new StringBuffer() 重开内存
    所有new都重开内存
      

  7.   

    面试遇到好多考官问String和StringBuffer的区别
      

  8.   

    首先弄清楚两个问题:
    1、 call by reference
    2、 finally执行的时机首先,在java中,call by reference只是传入reference 变量的值赋予子函数的局部变量,并不是真的把引用变量传进去。结合这次具体的例子,则为变量x1指向的地址,赋给子函数中的局部变量x。这样,x1与x指向同一个对象,当修改对象的内容时,如x.append("1"),会影响x1,因为x1指向的对象的内容发生了变化。但是,当局部变量x的值被修改,指向其他对象时,如x = new StringBuffer(),并不会影响x1。其次来看finally执行的时机。一般我们认为finally在renturn之前执行,但实际上在执行到return子句时,子函数会先将返回值放到主函数的“接收空间”中,再去执行finally中的内容。这样一来如果在finally中不重新return,是不会改变子函数的返回值的。在本例中,finally中有两次操作:一次修改了局部变量x指向的对象的内容x.append("3");一次修改了局部变量x的值,指向新的对象x = new StringBuffer("4")。因为函数返回值是x之前指向的对象,是在finally中的内容执行前就确定的,所以后一次操作(x = new StringBuffer("4"))对子函数的返回值是没有影响的。下面是执行过程的细节,如果上面的描述不够清晰,不好理解。可以先看一下下面的详细流程。StringBuffer x1 = new StringBuffer()
    x2 = new Test().inc(x1)... StringBuffer inc(StringBuffer x) 子函数开始执行...
    ...x.append("1")
    ...x = new StringBuffer()
    这里局部变量x指向的地址发生了变化,但x1并不会随之变化。
    ... return x
    这时子函数会把返回值放入主函数用于接收的“空间中”,然后去执行finally中的内容,finally中的内容执行完成后才会结束子函数。
    接着执行finally中的内容:
    ... x.append("3")
    ...x = new StringBuffer("4")
    注意这里并没有改变子函数的返回值,仅仅是局部变量X指向的地址发生了变化。
    理解这里后,可以明白这里对后来x2的赋值没有影响。
    (如果你在finally中最后在return x一次,子函数的返回值会改变,后来x2赋值时,会指向和局部变量x相同的地址。)
    ...子函数执行结束,回到x2 = new Test().inc(x1)
    接下来就会打印出结果。所以会出现“1”“3”。