[英]Object, reference and class. Need help understanding some code
我有點理解:
兩次調用以下代碼會發生什么?
Car batmobile = new Car();
是否會創建兩個對象? 如果是這樣,第一個對象發生了什么? 詳細地說,在類,對象和引用方面會發生什么?
第2部分:
這是一個無限循環嗎? 自構造函數創建對象以來,對象會繼續創建嗎? 類,對象,引用關系在這里如何工作?
public class Alphabet {
Alphabet abc;
public Alphabet() {
abc = new Alphabet();
}
}
汽車batmobile = new Car(); 是否會創建兩個對象?
如果調用兩次,則為是。 因為該行創建了一個對象的新實例。 因此,執行兩次將導致兩個新實例。 但是請注意,如果您嘗試連續兩次執行相同的確切行,則會出現編譯器錯誤,因為您將嘗試在同一作用域中重新聲明相同的變量。
但是否則,不會,在該行上僅創建一個對象。 兩次提到Car
是因為它聲明了變量( batmobile
)和構造函數( Car()
)的類型。 某些語言(C#,JavaScript,無類型語言等,但Java沒有)具有速記功能,因為很容易從第二種語言推斷出來。 例如:
var batmobile = new Car();
這是一個無限循環嗎?
不,這里沒有循環:
Public class Alphabet{
Alphabet abc;
Public Alphabet(){
abc = new Alphabet();
}
}
有 ,然而,一個堆棧等待飛越。 為了創建一個Alphabet
必須首先創建一個Alphabet
。 運行代碼,然后查看錯誤。 無限循環將無限執行(假設循環的每次迭代都不會增加某些有限資源的使用),例如:
while (true) {
Car batmobile = new Car();
}
這將無休止地執行。 但是,您發布的代碼將結束。 有錯誤。 因為每次對構造函數的調用都會在內部調用構造函數。 調用堆棧是有限的資源,因此它將很快耗盡。
我用一個cookie隱喻來解釋對象和類。
將計算機的內存想像成一大堆餅干面團。 (好吃,不是嗎?)
您的課程是小甜餅刀。 只要您有面團(記憶),它將創建特定大小和形狀的Cookie。 一個對象是用cookie切割器剪切的cookie。
1)batmobile是對Car對象的引用。 它只能指向Car或car的子類。 創建對象時,沒有附加對象實例(面團)。 調用new Car()時,將對象實例標記出來,並將其分配給名為batmobile的引用。 只有一個參考。
2)不要這樣做。 我不確定,您可能最終會導致堆棧溢出,但這不會為您帶來所需的結果。 您可能要查找Singleton模式。 它可能會幫助您。
現在,我需要幫助來了解兩次調用此代碼時究竟發生了什么。
例如:
Car batmobile = new Car();
是否會創建兩個對象?
每次執行該行時,都會創建一個Car
對象,因此,如果執行兩次,則將創建兩個對象。
如果是這樣,第一個對象發生了什么。
如果沒有其他引用,JVM就有資格對其進行垃圾回收。 何時以及是否發生這種情況取決於JVM的垃圾收集器中的許多因素。
有人可以詳細解釋在類,對象和引用方面會發生什么。
Car batmobile
...聲明一個Car
類型的變量。 因為它是對象類型,所以該變量最終將保存對象引用 (或null
,這意味着它不保存對任何對象的引用)。 實際對象獨立於可能引用它的任何變量而存在(並且可能有多個引用到一個對象)。 對象引用就像一個內存地址,說明對象在內存中的位置。 (它不是一個內存地址,但是就像一個。)
new Car();
...創建一個新的Car
對象,並調用Car
構造函數對其進行初始化。 所以:
Car batmobile = new Car();
...聲明一個變量,創建一個對象,調用Car
構造函數,並將對該對象的引用分配給batmobile
。
這是一個無限循環嗎?
可能會,但是最終您會耗盡堆棧空間,因此這是一個堆棧溢出錯誤 。 該行調用了Alphabet
構造函數,該函數調用了Alphabet
構造函數,該函數又調用了Alphabet
構造函數...您明白了。
問題1
Car batmobile = new Car();
這將創建一個對象。 該對象為Car
類型,其標識符為“ batmobile”。 根據其引用, batmobile
將被彈出到堆棧上,並且將包含對堆上Car
類型的對象的引用。
這個問題可能對堆棧和堆內存的解釋有所幫助。
問題2
具有諷刺意味的是,看到此示例已發布在SO上,則此示例將導致堆棧溢出錯誤。 每次對構造函數的調用都會創建一個新對象,並將對該對象的引用放在堆棧上,然后再次調用該構造函數。 堆棧是內存有限的區域,因此最終它將溢出,並且您的程序將因堆棧溢出錯誤而終止
在C ++中,編寫時:
SomeClass x;
它會自動創建SomeClass
的實例。 在Java中不是這樣。
在Java中,上面的同一行僅創建了一個名為x
的變量,其類型為SomeClass
。 變量x
在初始化為某種東西之前不會引用任何東西(任何實例)。
在Java中,下面的行創建一個對象,並初始化變量x
指向它。
SomeClass x = new SomeClass();
您的代碼塊:
Public class Alphabet{
Alphabet abc;
Public Alphabet(){
abc = new Alphabet();
}
}
實際上不執行任何操作,因為從不調用構造函數。 如果您確實這樣稱呼它:
public static void main(String[] args){
new Alphabet();
}
將會發生以下情況:
main
方法) abc
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.