按引用调用不符合预期

时间:2014-08-08 17:23:06

标签: java object static pass-by-reference

请考虑以下简短代码:

class abs{}
class cd
{
    static void method(abs a)
    {
        System.out.println(a); // PRINTS NULL
        a = new abs();
        System.out.println(a); // PRINTS NEWLY GENERATED HASHCODE
    }
    public static void main(String...args)
    {
        abs gh = null;
        // REFERENCE SET TO NULL

        // NOW PASSING IT TO A METHOD
        method(gh);

        // IF OBJECT CALL IS CALL BY REFERNCE, THEN WHY DOES THIS PRINT NULL ?
        System.out.println(gh);
    }
}

我的评论解释了我的意思。基本上,最后一个print语句应该打印哈希码,但是它会打印出#null;'。这背后的原因是什么?

4 个答案:

答案 0 :(得分:3)

Java is pass by value。这就是你的代码中发生的事情:

//gh initialized as null
abs gh = null;
//passing a copy of the value of the reference to the method
method(gh);
//gh keeps the value of the current reference which is null
System.out.println(gh);

更好的例子是尝试替换迭代List时获得的对象:

List<String> stringList = Arrays.asList("hello", "world");
System.out.println(stringList);
for (String currentString : stringList) {
    //naively trying to change the contents from ["hello", "world"] to ["bye", "world"]
    if (currentString.equals("hello")) {
        currentString = "bye";
    }
}
System.out.println(stringList);

输出:

["hello", "world"]
["hello", "world"]

这是因为增强的for循环将与迭代器提供的引用副本一起使用。上面的for循环代码可以转换为:

for (Iterator<String> it = stringList.iterator(); it.hasNext(); ) {
    String currentString = it.next();
    //now, it's more clear that you're updating the variable currentString
    //that holds a copy of the reference stored in the List
    //this explains why this approach won't work
    if (currentString.equals("hello")) {
        currentString = "bye";
    }
}

答案 1 :(得分:1)

Java是一种值传递语言。这就是为什么gh调用不会更改method变量的原因。如果您希望method返回method中创建的实例,请让method返回它:

class cd
{
    static abs method()
    {
        abs a = new abs();
        System.out.println(a);
        return abs;
    }
    public static void main(String...args)
    {
        abs gh = null;
        gh = method();
        System.out.println(gh);
    }
}

答案 2 :(得分:1)

在您的代码中&#39; gh&#39;和&#39; a&#39;是两个方法局部变量。通过将gh设置为null并将其发送到名为method的静态方法!你没有将任何对象引用传递给&#39; a&#39;。 Null不表示任何对象引用。因此对局部变量&#39; a&#39;进行了更改。没有反映到&#39; gh&#39;。

答案 3 :(得分:0)

你有一个类abs的对象。然后你把它传递给你的函数。直到没有问题(期望它为空)。

现在,在您的函数中,您重新分配此变量。在你的方法里面,一切都很好。

在您的方法之外,没有人认识到变量发生了变化。所以它仍然是空的。这就是为什么上面的代码不应该编译btw。

你想要的是method()返回对象。代码:

static abs method ()
{
    return new abs();
}
public static void main (String[] args)
{
    abs gh = method();
    System.out.println(gh); // this won't print null
}