亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java 函數調用。非平凡對象是否通過引用復制?

Java 函數調用。非平凡對象是否通過引用復制?

慕尼黑的夜晚無繁華 2023-09-27 10:22:43
幾周前我開始接觸java。在此之前,我在嵌入式目標上使用 c/c++ 工作,并在 Win PC 上使用帶有 UI Stuff 的 c# 工作多年。我得到了這個非常簡單的例子: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);    }}我希望無論 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;    }}Streamfiller 應該修改它的流副本,而不是原始引用public class StreamFiller {    public static void fillStream( Stream stream ) {         stream.writeString( "This is a" );         stream.writeString( " stream." );    }        }如果我錯了,請糾正我,但由于字符串類的實際文本是在堆上分配的,因此 StreamProcessing () Stream 對象和 fillStream() 的(假定復制的)本地對象都指向相同的地址堆(是的,我現在它不是像 c/c++ 中那樣的實際內存地址,而是一些唯一的對象標識符)那么我的假設正確嗎?非平凡對象(又名在堆上分配的對象)是通過引用傳遞的嗎?
查看完整描述

2 回答

?
瀟湘沐

TA貢獻1816條經驗 獲得超6個贊

Java 語言不允許您像 C 和 C++ 那樣在代碼中區分堆/堆棧。

相反,它將所有數據類型分為兩組:

  1. 基本類型:
    這些是簡單的內置數字類型,例如int,doubleboolean(不是 Java 中的數字類型)。
    注意String不是這樣的類型!

  2. 對象類型:
    如果是類,那么它就是對象類型。這適用于內置類型(例如)String和用戶定義類型(例如您的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++ 中,該行將A var2 = var1;調用復制構造函數并創建一個新對象,但在 Java 中沒有這樣的事情。如果你想要一個副本,你需要clone顯式調用方法。

保存var1和復制的內容var2只是一個參考。所以兩個變量“指向”同一個對象。

再說一遍——課程是否瑣碎并不重要。即使一個類完全是空的,您仍然只能獲得并使用對該類的任何對象的引用。

至于前面提到的基本類型,Java 有諸如IntegerBooleanfor 它們的包裝類。您可能想閱讀有關“裝箱”和“拆箱”的內容。

還要注意的另一件事是,某些類型是不可變的 - 也就是說,它們不提供在創建后更改數據的方法。

String在Java中是一種不可變類型,但它也與任何其他類型有所不同。
它有特殊的特權。
雖然 Java 不像 C++ 那樣支持運算符重載,但對于String類型,該語言確實提供了一種特殊的方法+ operator來執行字符串連接。

然而,由于String對象是不可變的,任何串聯操作都會創建一個全新的String對象,甚至是這樣的:

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

這將創建一個新字符串“Hello world”并將對其的引用存儲在 中a,而對舊“Hello”字符串的引用將在將來的某個時刻被垃圾收集。


查看完整回答
反對 回復 2023-09-27
?
森林海

TA貢獻2011條經驗 獲得超2個贊

盡管在 Java 中一切都是按值傳遞的,但是原始數據類型(例如 int、char 和 boolean)與引用數據類型傳遞給方法的方式之間存在差異。當傳遞原始數據類型的值時,該值只能在特定方法的范圍內更改。當傳遞引用數據類型的值時,引用將保持不變,但值將全局更改(或在對象初始化的任何范圍內)。

查看完整回答
反對 回復 2023-09-27
  • 2 回答
  • 0 關注
  • 136 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號