对java中的内存感到困惑

对java中的内存感到困惑,java,pointers,memory,pass-by-reference,Java,Pointers,Memory,Pass By Reference,据我所知,java中的对象是通过引用传递的,或者更准确地说,对对象的引用是通过值传递的。那么,如果我声明一个字符串并将其传递到一个函数中,在这个函数中我更改了字符串的值,为什么原始字符串没有更改?例如: class Thing { static void func(String x){ x = "new"; } public static void main(String [] args) { String y = "old"; fu

据我所知,java中的对象是通过引用传递的,或者更准确地说,对对象的引用是通过值传递的。那么,如果我声明一个字符串并将其传递到一个函数中,在这个函数中我更改了字符串的值,为什么原始字符串没有更改?例如:

class Thing 
{

    static void func(String x){ x = "new"; }

    public static void main(String [] args)
    {
        String y = "old";
        func(y);
        System.out.print(y);
    }
}
为什么y的值仍然是“旧的”

编辑:为什么下面将某物的属性x设置为90

class Thing { int x = 0; 

static void func(Thing t){ t.x = 90; }

public static void main(String [] args){
    Thing something = null;
    something = new Thing();
    func(something);
    System.out.print(something.x);
}
}

首先,java中的一切都是按值传递的。甚至引用也是按值传递的

您已经创建了一个新的
字符串
literal,并且没有在方法
func()
中返回该字符串

您正在修改传递的参数,而不是原始的
字符串
,因此无法看到更改

你可能需要这个

public static void main(String [] args)
    {
        String y = "old";
        y= func(y);
        System.out.print(y);
    }

 static String func(String x){ 
  x = "new";  
  return x
 } 
编辑评论:

不,它们不一样。两种
字符串
的方式有很大的不同,特别是在内存方面

阅读

Edit2:

在第一种情况下,您将在
func
方法中创建一个新的字符串文本,但在这里您将修改引用

当你完成时,你的怀疑就澄清了

  static void func(Thing t){
     t = new Thing(); //as like previous example
     t.x = 90;       // points to new one. Not the original.

    }
现在检查结果。

如前所述:

Java通过值传递一切,而不是通过引用——请确保 记住这一点。当我们说每件事时,我们意味着每件事—— 对象、数组(Java中的对象)、基元类型(如 int和float)等–在Java中,这些都是通过值传递的。什么 传递值和传递引用之间的差异是多少?什么时候 将一个参数(甚至多个参数)传递给一个方法,Java 将在原始文件中创建一个或多个值的副本 变量,并将其作为参数传递给方法,这就是原因 它被称为按值传递。具有传递值的键是 方法将不会接收正在传递的实际变量–但是 只是存储在变量中的值的副本


在Java中,对象和字符串的处理方式不同,字符串在Java中保持不变

要在您的示例中更加清楚,请执行以下操作:

假设字符串y指向内存位置2000,字符串x指向内存 位置2001,所以得到相同的旧值

如果是对象,请参考我的示例:


它与不变性无关。所有这些都是关于如何传递参数和变量的范围

这是您的函数调用

String y = "old"; // The reference y pointing to the string object "old": y ---> "old"
func(y);  
当您输入被调用的函数时

static void func(String x){  // x = y which means x now points to "old": x ---> "old"
    x = "new"; // x ---> "new": now the local variable x is pointing to a different object. y still points to "old".
} //Scope of x ends here
当我们打印它的时候

System.out.println(y);
y仍然指向“旧”。一个新的字符串对象被分配给了方法func的本地x。因此,它仍然打印“旧”

所以,如果我声明一个字符串并将其传递到一个函数中 字符串的值,为什么原始字符串不更改

需要知道的重要一点是,不能声明值为字符串的变量——字符串(即对象)在Java中不是值<代码>y
是一个引用(指向对象的指针)。Java中唯一的类型是基元类型和引用类型。类型
字符串
是引用类型

因此,您正在传递一个引用(指向对象的指针)。在函数内部,
x
同样是一个引用(指向对象的指针)。更改引用的值(例如,将(
=
)赋值为
x
)不会对它可能指向的对象产生任何影响


操作符允许您访问引用指向的对象的字段。分配给
访问的结果会更改引用指向的对象,而不是引用本身。这些都是非常不同的东西。

Sklak,把x=“ABC”想象成与x=newstring(“ABC”)相同的东西。为什么下面将Thing的属性x设置为90?(参见有问题的编辑)@SKLAK请检查更新。你们两个例子是不同的。第一种情况是创建一个新字符串,第二种情况是不创建字符串,那么为什么我们能够更改对象的属性呢。例如,假设你有一辆拥有速度和颜色属性的汽车。假设在这个类中有一个静态函数,它将通过的汽车的速度设置为100。如果我在main中创建一个名为carx的汽车,并执行类似setSpeed(carx)的操作,carx.getSpeed()是否会返回100?你不能只在从其他地方复制的答案底部转储一个链接。您需要清楚地引用此内容,以表明这些内容都不是您的原始文字。我在上面已经这样做了。“我们指的是一切——对象、数组(Java中的对象)、基本类型(如int和float)等等——这些都是Java中按值传递的”“对象”在Java中不是值,不能“传递”。