Java函数调用。非平凡对象是否通过引用复制?

Java函数调用。非平凡对象是否通过引用复制?,java,Java,几周前我开始使用java。在此之前,我曾在嵌入式目标上与c/c++合作多年,在Win PC上与c#一起使用UI 我得到了一个非常简单的例子: public class StreamProcessing { public static void main(String[] args) { Stream stream = new Stream(); //after this line: Stream string empty StreamFiller.fi

几周前我开始使用java。在此之前,我曾在嵌入式目标上与c/c++合作多年,在Win PC上与c#一起使用UI

我得到了一个非常简单的例子:

public class StreamProcessing {

    public static void main(String[] args) {
        Stream stream = new Stream(); //after this line: Stream string empty

        StreamFiller.fillStream(stream);   //after this line: Stream string not empty any more
        StreamPrinter.printStream(stream);

    }

}
public class A {
    public int a;

    public static void main(String [] args) {
        A var1 = new A();
        A var2 = var1;

        var1.a = 42;

        System.out.println("var2.a = " + var2.a);
    }
}
我希望无论StreamFiller.fillStream()做什么,参数都会被复制。但是,看起来fillStream正在修改实际的流对象本身。 Stream类基本上包含一个字符串

public class Stream {
    private String content = "";
    int index = 0;

    public char readChar() {
        if (index < content.length()) {
            return content.charAt(index++);
        } else {
            return 0;
        }
    }

    public void writeString(String str) {
        content += str;
    }
}
如果我错了,请纠正我,但是由于字符串类的实际文本是在堆上分配的,StreamProcessing()流对象和fillStream()的(假定复制的)本地对象都指向堆上的同一地址(是的,我现在不是像c/c++中那样的实际内存地址,而是某个唯一的对象标识符)

那么我的假设正确吗?非平凡对象(即堆上分配的对象)是通过引用传递的吗


thx为您提供帮助:)

即使在Java中,所有内容都是按值传递的,但基本数据类型(如int、char和boolean)和引用数据类型传递给方法的方式也存在差异。 传递基元数据类型的值时,只能在特定方法的范围内更改此值。传递引用数据类型的值时,引用将保持不变,但值将全局更改(或在初始化对象的任何范围内更改)


也请参阅更多信息:

< P> java语言不允许您在代码中堆/栈区分C和C++做的方式。

相反,它将所有数据类型分为两组:

  • 基本类型:
    这些是简单的内置数字类型,如
    int
    double
    boolean
    (在Java中不是数字类型)。
    请注意,
    String
    不是这种类型

  • 对象类型:
    如果它是一个类,那么它就是一个对象类型。这适用于内置类型,如
    String
    ,以及用户定义的类型,如
    类。
    对于这些类型,无论您查看的是局部变量、类成员、实例成员还是函数参数,都只能看到一个引用

  • 让我们看一个简单的例子:

    public class StreamProcessing {
    
        public static void main(String[] args) {
            Stream stream = new Stream(); //after this line: Stream string empty
    
            StreamFiller.fillStream(stream);   //after this line: Stream string not empty any more
            StreamPrinter.printStream(stream);
    
        }
    
    }
    
    public class A {
        public int a;
    
        public static void main(String [] args) {
            A var1 = new A();
            A var2 = var1;
    
            var1.a = 42;
    
            System.out.println("var2.a = " + var2.a);
        }
    }
    
    如果编译并运行此示例,它将打印42。
    在C++中,行<代码> VAR2= VAR1;
    会调用一个复制构造函数并创建一个新对象,但在Java中没有这样的东西。如果需要副本,则需要显式调用
    clone
    方法

    保存在
    var1
    中并复制到
    var2
    的内容只是一个参考。 所以两个变量“指向”同一个对象

    再说一遍,这个类是否微不足道并不重要。即使一个类是完全空的,您仍然只会得到一个对这个类的任何对象的引用

    至于前面提到的基本类型,Java为它们提供了
    Integer
    Boolean
    等包装类。 你可能想了解一下

    还有一点需要注意的是,某些类型是不可变的——也就是说,它们不提供在创建数据后更改数据的方法

    String
    在Java中是一种不可变的类型,但它与任何其他类型也有点不同。
    它有特权。
    虽然java不支持C++之类的操作符重载,但是对于String 类型,语言确实提供了一个特殊的<代码> +操作符<代码>预处理字符串连接。 然而,由于
    String
    对象是不可变的,因此任何串联操作都将创建一个全新的
    String
    对象,即使是这样的对象:

    String a = "Hello";
    a = a + " world!";
    

    这将创建一个新字符串“Hello world”,并将对它的引用存储在
    a
    中,使对旧“Hello”字符串的引用在将来某个时候被垃圾收集。

    在Java中,对象总是按引用传递,只有像
    int
    这样的原语才按值传递。堆或堆栈并不重要。这在SO和web上都是重复的。通过值传递引用;没有复制。可能是复制的