为什么可以';我的Java方法不能更改传递的变量吗?

为什么可以';我的Java方法不能更改传递的变量吗?,java,variables,null,pass-by-reference,pass-by-value,Java,Variables,Null,Pass By Reference,Pass By Value,当我看到下面的代码没有按预期工作时,我有点困惑 我认为Java总是通过引用将变量传递到函数中。因此,为什么函数不能重新分配变量 public static void main(String[] args) { String nullTest = null; setNotNull(nullTest); System.out.println(nullTest); } private static void setNotNull(String s) { s = "not nul

当我看到下面的代码没有按预期工作时,我有点困惑

我认为Java总是通过引用将变量传递到函数中。因此,为什么函数不能重新分配变量

public static void main(String[] args) {

  String nullTest = null;

  setNotNull(nullTest);

  System.out.println(nullTest);
}

private static void setNotNull(String s) {
  s = "not null!";
}

该程序输出
null

对对象的引用是通过Java中的值传递的,因此分配给方法中的局部变量不会改变原始变量。只有局部变量
s
指向新字符串。用一点ASCII艺术可能更容易理解

最初,您有:

------------
| nullTest |
------------
     |
    null
第一次输入setNotNull方法时,会在
s
中获得nullTest值的副本。在这种情况下,nullTest的值是空引用:

------------    ------------
| nullTest |    |    s     |
------------    ------------
     |               |
    null            null
然后重新分配s:

------------    ------------
| nullTest |    |    s     |
------------    ------------
     |               |
    null         "not null!"
然后离开方法:

------------
| nullTest |
------------
     |
    null

Java不通过引用传递,而是传递引用的值。当您分配
s=“notnull”
时,您正在重新分配该值

s =
这就是为什么。您正在指定给,而不是修改s指向的对象

我希望在不使用o=setNotNull(o)的情况下做一些类似setNotNull(MyObject o)的事情

简单地说,你不能。您将得到的最接近的结果如下:

public class MyRef<T> {
    private T obj;

    public T get() {
        return obj;
    }

    public void set(T obj) {
        this.obj = obj;
    }

    public void setNotNull(T obj) {
        if (this.obj == null) {
            this.obj = obj;
        }
    }
}

MyRef<MyObj> ref = new MyRef<MyObj>();
ref.setNotNull(xyz);
System.err.println(ref.get());
公共类MyRef{
私人T obj;
公共部门得不到{
返回obj;
}
公共无效集(T obj){
this.obj=obj;
}
公共无效setNotNull(T obj){
if(this.obj==null){
this.obj=obj;
}
}
}
MyRef=新的MyRef();
参考setNotNull(xyz);
System.err.println(ref.get());

这些东西都很笨重,可能不值得这么做。

那么物体呢?我已经以一种强烈的反noob的态度得到了一般性的答案,并且已经找到了一种很好的解释记忆结构的方法+1@Lord.Quackster java处理对象的方式与基本类型没有区别。两者都是按值传递的。但是,由于java使用对象的“引用”进行操作,因此可以对传递的引用进行变异。但是由于引用本身是按值传递的,所以引用不能重置为其他内容。@TheLQ:我想说Java是按变量值的副本传递的。对于原语,复制的值是值本身;对于对象,复制的值告诉JVM如何在堆内存中检索对象。在讨论这个问题时,我不喜欢使用字符串,因为它们是不可变的(尽管如此,字符串是一个对象)。更多信息:这并不意味着什么。可以实例化任何可以实例化的内容,但不能更改调用方传递给您的值。