java 引用传递、返回 疑惑

代码如下:

public static void main(String[] args) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        A a = dispatcherServlet.new A("bb");
        dispatcherServlet.da(a); // 此行执行完毕,a.getA()值是bb
        System.out.println(a.getA());
    }

    private A da(A a) {
        a = new A("aaaaa");
        return a;
    }

    class A {
        private String a;

        public A(String a) {
            this.a = a;
        }

        public String getA() {
            return a;
        }

        public void setA(String a) {
            this.a = a;
        }

    }

疑惑如注释。为何da方法里的new值回到main后会丢失?

经学习得出以下结论:

  1. java只有值传递,没有引用传递
  2. 非原始类型也是值传递,传递的是值是该引用,为副本

因此:

  1. 在da中修改a的属性值,可以在da方法外生效。
  2. 在da中修改a的引用(重新对a赋值),修改的是引用副本。在da方法外不生效!

希望对其它碰到这种问题的人,不明所以的人有所帮助!!哈哈\(^ ^)/

阅读 8.1k
9 个回答

虽然说, java没有把指针明文写出来, 但是还是有用到指针的.
dispatcherServlet.da(a); // 这里虽然写的是a这个对象, 但是在方法里使用的是引用

private A da(A a) { // 这里是一个指针对象, 指向上方传入的 那个对象
    a = new A("aaaaa"); // 这里只是改变了 指针对象 并没有修改 源对象.
    return a; // 如果你想获得新的对象, 那就取这个返回值来用吧.
}

java里面分为对象, 和 对这个对象的引用对象(或者说指针?).
举例:
仓库里的货a, 和这个a货的清单 qd_a, 清单上写了a货在哪个仓库, 哪个区域的哪个位置.
有人把qd_a上的数据改了, 指向了货b, 但是货a却没有受影响, 受影响的是 qd_a这个清单.

这是我理解的.不知道解释清楚了没.. 希望指正.

    private A da(A a) {
        a = new A("aaaaa");
        return a;
    }

把这里的a改为成员变量即可

Cprivate:
    A da(A &a) {
        a = new A("aaaaa");
        return a;
    }

Java是没有引用传递的,也就是说Java不可能让你把整个参数的引用给替换掉。C/C++有引用传递,不过你必须要在参数的前面加上&符号。

java传值,不是传引用,只不过传的是指针的值,所以看起来像引用。。。

da里面

a = new A("aaaaa");

这一句是反映不到函数外面的,a的值(地址)在函数内修改了是没用的,但a的内容可以修改
比如da里面如果有

a.setA("aaaaa");

那你在函数外面打印出来的值就是"aaaaa"了

和这样的C++等价

void f(A *a) {
    a = new A("aaaaa");
}

void main() {
    a = new A("bb");
    f(a);
    cout << a.getA(); // "bb"
}

java只有值传递,没有引用传递
正解,传对象的时候一定要记住你传的不是这个对象自己的内存地址,而是这个对象的值,而这个值就是这个对象引用的地址

我感觉java传递参数的是分情况的吧,
对容器对象比如Map,是传递了引用而不是复制了值
在函数中对map容器的处理是会变化到原始原始调用者, 这就不能叫传值了吧...
简单类型是传值没错

对于非原始类型,引用放在栈上,对象本身放在堆上,栈上的引用会复制一份,对象不复制。

java如果想实现引用传递,可以用boxing,即用数组来存取。

private void foo(int[] iarr)
{
    int ival = iarr[0];
    // ...
    iarr[0] = ival;
}

朋友,看到这儿我必须说一句,Java是引用传值,我今天才遇到这样的问题,再重复一遍Java是引用传值。你写的代码有看起来有点麻烦,我把类和方法名改了一下,看起来清晰一点`public class CallTest {

public static void main(String[] args) {
    CallTest dispatcherServlet = new CallTest();
    TypeA typeA = dispatcherServlet.new TypeA("bb");// 调用了TypeA的构造方法,新建了一个TypeA的实例
    dispatcherServlet.callMethod(typeA); // 此行执行完毕,a.getA()值是bb
    System.out.println(typeA1.getFieldA());
}

private TypeA callMethod(TypeA typeA) {// 调用了TypeA的构造方法,新建了一个TypeA的实例
    typeA = new TypeA("aaaaa");
    return typeA;
}

class TypeA {
    private String fieldA;

    public TypeA(String fieldA) {
        this.fieldA = fieldA;
    }

    public String getFieldA() {
        return fieldA;
    }

    public void setFieldA(String fieldA) {
        this.fieldA = fieldA;
    }
}

}`
我再注释上也写了,你实际上创建了两个对象,并没有修改值或者引用,他们就是两个对象,你只是取了其中的一个对象而已。如果你希望输出的结果是“aaaaa”的话,你就取另一个对象就行了,不过你又希望输出结果是"aaaaa"又取错了对象就导致这样的结果了,如果希望结果是“aaaaa”,可以看下面的代码。

public class CallTest {
    public static void main(String[] args) {
        CallTest dispatcherServlet = new CallTest();
        TypeA typeA = dispatcherServlet.new TypeA("bb");// 调用了TypeA的构造方法,新建了一个TypeA的实例
        TypeA typeA1 = dispatcherServlet.callMethod(typeA); // 此行执行完毕,a.getA()值是bb
        System.out.println(typeA1.getFieldA());
    }

    private TypeA callMethod(TypeA typeA) {// 调用了TypeA的构造方法,新建了一个TypeA的实例
        typeA = new TypeA("aaaaa");
        return typeA;
    }

    class TypeA {
        private String fieldA;

        public TypeA(String fieldA) {
            this.fieldA = fieldA;
        }

        public String getFieldA() {
            return fieldA;
        }

        public void setFieldA(String fieldA) {
            this.fieldA = fieldA;
        }
    }
}

楼主,希望你能看到,不希望楼主因为自己的代码出现了问题就对java语言造成错误的理解。补充一下,基本类型是值传递的,String和包装类也会将一些值存进常量池。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题