Java传递值 - 你能解释一下吗?

时间:2010-07-05 20:43:17

标签: java reference

我读了this excellent article并且它有意义:Java严格按值传递;当一个对象是一个参数时,对象的引用按值传递

但是,我完全混淆了为什么以下代码段可能会起作用。 Foo有一个String成员变量a,它是不可变的,每次都需要刻录。 第一种刻录方法(注释掉)应该可以正常工作。 第二个方法设置a对传递的值的引用。如果newstr是临时变量,它应该不起作用。预期的输出结果是:

Totally temp
NULL

然而,我得到了

Totally temp
Totally temp

为什么呢?临时变量引用仍然很好,这只是纯粹的运气吗?

public class Foo {
    String a;
    public Foo(){}
    public void burna(String newstr){
           // a = new String(newstr);
           a = newstr; /*this should not work: */ 
        }
}

public class foobar {
    Foo m_foo;
    public foobar(){};
    public void dofoo(){
        String temp = new String("Totally temp\n");
        m_foo.burna(temp);
        System.out.print(m_foo.a);
    }

}

 public static void main(String[] args) {
        Foo myfoo = new Foo();
        foobar myfoobar = new foobar();

        myfoobar.m_foo = myfoo;
        myfoobar.dofoo();
        System.out.print(myfoo.a);

    }

6 个答案:

答案 0 :(得分:11)

  

Foo有一个String成员变量a,它是不可变的,每次都需要刻录。

不,它没有:它没有标记为final

public class Foo {
    String a;
    ...
}

变量是完全可变的 - 您可以随时更改它以引用不同的字符串,这就是您在burna方法中所做的。

我目前不知道为什么你认为这不起作用:

public void burna(String newstr){
    a = newstr; /*this should not work: */ 
}

a设置为newstr - 这是对字符串的引用(或null)。这就是它所做的一切。我不确定你在变量中“燃烧”是什么意思。

您正在调用burna并传入对文本为“Totally temp \ n”的字符串的引用 - 因此a设置为对该字符串的引用。

你是什么意思“如果newstr是一个临时变量,它应该不起作用。”没有“临时变量”这样的东西。有一个本地变量 - 但是一个对象不会因为引用它的变量超出范围而被销毁。那会让你感到困惑吗?

你的程序有几件事情发生了 - foobar类在理解方面可能没有帮助你。您是否可以尝试将代码简化到令您感到困惑的程度,但是进展较少?然后我们可以更准确地隔离混淆的来源。

答案 1 :(得分:3)

问题似乎是您不了解垃圾收集的工作原理。只要对象的至少一个引用保持有效,就不会收集该对象。

答案 2 :(得分:2)

字符串“Totally temp \ n”有两个引用。一个是temp,另一个是a对象中的Foo。在dofoo temp结尾处超出范围,因此减少了一个参考。但是你还有另一个引用,所以字符串不是垃圾回收。

答案 3 :(得分:2)

String对象是不可变的,但Foo对象不是。 myfoobar.m_foomyfoo指向同一个对象,因此共享a成员。

答案 4 :(得分:1)

您可能习惯了变量和对象在C ++中的工作方式。

非原始类型的变量总是引用到Java中的对象,与C ++不同,其中变量代表对象本身。

Java中的对象始终在堆上分配。对象永远不会在堆栈*上作为“临时变量”,就像在C ++中一样。

*:实际上,JVM可能会做一些优化并将对象放在堆栈上,但这与理解变量和对象在Java中的工作方式无关。

答案 5 :(得分:0)

由于Java也按值传递对象引用。现在,这里变得棘手:

public void tricky(Point arg1,Point arg2)

{

arg1.x = 100;

arg1.y = 100;

Point temp = arg1;

arg1 = arg2;

arg2 = temp;

}

public static void main(String [] args)

{

点pnt1 =新点(0,0);

点pnt2 =新点(0,0);

System.out.println(“X:”+ pnt1.x +“Y:”+ pnt1.y);

System.out.println(“X:”+ pnt2.x +“Y:”+ pnt2.y);

System.out.println(“”);

棘手(PNT1,PNT2);

System.out.println(“X:”+ pnt1.x +“Y:”+ pnt1.y);

System.out.println(“X:”+ pnt2.x +“Y:”+ pnt2.y);
}

**如果我们执行这个main()方法,我们会看到以下输出:

X:0 Y:0

X:0 Y:0

X:100 Y:100

X:0 Y:0 **