Java 反直观的对象参数行为

Java 反直观的对象参数行为,java,parameters,pass-by-reference,pass-by-value,Java,Parameters,Pass By Reference,Pass By Value,我很清楚Java是按值传递参数的,并且知道由于对象作为引用保存在变量中,所以当这些值是可变的时,可以更改对象值。我还了解到,类字符串包含不可变的对象。因此,为了测试我的理解力,我决定编写一段代码,将对象作为参数传递给方法,更改其字符串和int变量,然后打印它。我希望,由于参数只是一个副本,这些更改不会影响传入的变量。作为参数传入对象是否不会将整个对象复制到新变量中,而只是传递该对象引用?这与一些消息来源告诉我的相反。以下是相关代码: public class Test { publi

我很清楚Java是按值传递参数的,并且知道由于对象作为引用保存在变量中,所以当这些值是可变的时,可以更改对象值。我还了解到,类字符串包含不可变的对象。因此,为了测试我的理解力,我决定编写一段代码,将对象作为参数传递给方法,更改其字符串和int变量,然后打印它。我希望,由于参数只是一个副本,这些更改不会影响传入的变量。作为参数传入对象是否不会将整个对象复制到新变量中,而只是传递该对象引用?这与一些消息来源告诉我的相反。以下是相关代码:

public class Test {


    public int testVar = 20;
    public String testString = "Hello";

    public static void testCheck(Test test){
        test.testString = new String("GoodBye");
        test.testVar = 10;
    }

    public void printTest(){
        System.out.println("testVar: " + testVar + " testString: " + testString);
    }

    public static void main(String[] args) {
        Test test1 = new Test();
        test1.printTest();
        testCheck(test1);
        test1.printTest();

    }

}
输出:

testVar: 20 testString: Hello 

testVar: 10 testString: GoodBye 
预期:

testVar: 20 testString: Hello

testVar: 20 testString: Hello

提前感谢。

您正在将引用的副本传递给原始对象。实际上,您正在传递原始对象的引用,因此:

testCheck(test1);
您正在修改
test1
对象的属性/变量。

一些概念:

  • 对象是具有数据和行为的构造
  • 变量是存储值的结构
  • 对象引用是引用对象的值
  • 引用类型的变量(所有不是基元类型的类型)将对象引用存储为其值
  • 当您从变量访问字段或调用方法时,JVM将取消引用对象引用的值,获取对象,并为您执行访问或调用
最后一点是您在
testCheck
方法中所做的。而且

  • 方法参数是在方法定义中声明的变量
  • 方法参数是在调用方法时希望绑定到方法参数的值
  • Java传递(按值)并将对象引用的值绑定到方法参数
作为参数传入对象是否不会复制整个对象 将对象引用传递到新变量中


那句话没有多大意义。作为参数传递的是一个值。该值是对象引用,而不是对象。在方法中,您可以取消对该对象引用的引用,以访问被引用对象的字段并调用其方法。

在Java中,参数总是按值传递,因此
test
实际上是
test1
的副本。您所犯的错误是,复制对象变量并不复制对象;它将引用复制到同一对象。由于在同一对象实例上对字段进行变异,因此两个引用都看到了新的状态。相比之下,当您“更新”一个不可变的对象变量(如
字符串
)时,您只是引用了一个新的对象实例

顺便说一句,很少有好的理由创建一个
新字符串
,而不仅仅是分配一个字符串文本。在这种情况下肯定没有