Java - 按值傳遞 - 垃圾收集

[英]Java - Pass By Value - Garbage Collection


Trying to fully grasp Java's pass-by-value. Let's say we have this code:

試圖完全掌握Java的傳值。假設我們有這個代碼:

public class Test {

    static void switchIt(Test t) {
        t = new Test();
    }

    public static void main(String ... args) {
        Test a = new Test();
        switchIt(a);
    }
}

When the object referenced by a gets passed to switchIt(), the reference value is copied to t. So we'd have two different reference variables, with identical bit-patterns that point to a single object on the heap.

當a引用的對象傳遞給switchIt()時,引用值將復制到t。所以我們有兩個不同的引用變量,相同的位模式指向堆上的單個對象。

When t = new Test() runs, obviously a still refers to the old object, and t now points to a new object on the heap. Since the a and t reference variables used to have identical bit-patterns, does this mean that Java implicitly changed the bit-pattern of the t reference variable? Or is it wrong to assume that the bit patterns were ever identical to begin with?

當t = new Test()運行時,顯然仍然引用舊對象,而t現在指向堆上的新對象。由於a和t引用變量曾經具有相同的位模式,這是否意味着Java隱式地改變了t引用變量的位模式?或者假設位模式始終相同是錯誤的?


Let's say the a reference variable is represented on the stack as 0001. When I pass it to the function, that means t is also represented on the stack as 0001, since I passed a copy of the bits in the reference variable.

假設一個引用變量在堆棧上表示為0001.當我將它傳遞給函數時,這意味着t也在堆棧上表示為0001,因為我傳遞了引用變量中的位副本。

When I assign t to a new Test(), if t and a both are represented as 0001 on the stack, would that 0001 change for t?

當我將t分配給新的Test()時,如果t和a兩者在堆棧上表示為0001,那么0001會改變t嗎?

4 个解决方案

#1


1  

Think of it this way:

想一想:

Java isn't passing the object, it's passing the memory pointer of the object. When you create a new object, it gets a new pointer. So when we say java always passes by value, it's because it's always passing the pointer of the object which is a numeric value.

Java沒有傳遞對象,它傳遞了對象的內存指針。創建新對象時,它會獲得一個新指針。所以當我們說java總是按值傳遞時,它是因為它總是傳遞對象的指針,這是一個數值。

Even though the objects are equal to one another (a.equals(t)) may return true - they are not identical because they have different pointers and are thusly different objects residing in different memory space.

即使對象彼此相等(a.equals(t))也可能返回true - 它們不相同,因為它們具有不同的指針,因此是駐留在不同存儲空間中的不同對象。

Using your edit example. a would have 0001 but t would be 0002

使用您的編輯示例。 a會有0001但是t會是0002

Is Java "pass-by-reference" or "pass-by-value"?

Java是“傳遞引用”還是“按值傳遞”?

Hope that helps

希望有所幫助

#2


2  

Yes, the reference for t would change to point to the newly-allocated Test instance. Your understanding is correct on that point.

是的,t的引用將更改為指向新分配的Test實例。在這一點上你的理解是正確的。

When the switchIt() method returns, there are no longer any references to that new object. It is now eligible for garbage collection, while the original object that a continues to reference will not be collectible until main() returns.

當switchIt()方法返回時,不再有對該新對象的任何引用。它現在有資格進行垃圾收集,而繼續引用的原始對象在main()返回之前將無法收集。

#3


1  

I think you got it, but you didn't phrase it too well. Here's a more in depth explanation, though the implementation may not be 100% exactly as I'm describing.

我想你明白了,但是你沒有說得太好。這是一個更深入的解釋,雖然實現可能不是我所描述的100%。

When you compile that code, a structure called a "stack frame" will be created for each of your methods. Each stack frame will hold enough space in it for parameters, local variables and so on. Basically it will have enough resources for your method to do its thing. All these stack frames are placed in "the stack" :)

編譯該代碼時,將為每個方法創建一個稱為“堆棧幀”的結構。每個堆棧幀將在其中保留足夠的空間用於參數,局部變量等。基本上它將有足夠的資源讓你的方法做它的事情。所有這些堆棧幀都放在“堆棧”:)

When you run your code, in main you create a new instance of Test and assign the reference to variable a or, more precisely, to the location in the stack frame reserved for variable a. The actual object will be stored on the heap and your variable a will only hold the memory address of that object, as you already seem to know.

運行代碼時,在main中創建一個新的Test實例,並將引用分配給變量a,或者更確切地說,分配給為變量a保留的堆棧幀中的位置。實際的對象將存儲在堆上,而變量a只保存該對象的內存地址,正如您已經知道的那樣。

When you call switchIt, the runtime will send a copy of the reference a to the stack frame of the method switchIt. This stack frame has enough space for your parameter and it will store it in its reserved space. But what you're doing in switchIt is replacing the initial value stored in that reserved space with a new reference from a new object that has just been created and placed on the heap. Now you have two objects on the heap, each stack frame containing one of these references.

當您調用switchIt時,運行時會將引用a的副本發送到方法switchIt的堆棧幀。此堆棧幀具有足夠的空間用於您的參數,並將其存儲在其保留空間中。但是你在switchIt中所做的是用剛剛創建並放在堆上的新對象替換存儲在該保留空間中的初始值。現在堆上有兩個對象,每個堆棧框架包含其中一個引用。

#4


1  

I think the code will clear you more .Check the hash code in each print statement it is not the memory location but it will help you to understand the answer of your question.

我認為代碼會更清楚你。檢查每個print語句中的哈希碼,它不是內存位置,但它可以幫助你理解你的問題的答案。


class Ideone
{
 static void switchIt(Ideone t) {
     System.out.println("Object t "+t); // print statement 2
        t = new Ideone();
     System.out.println("object t after changing t "+t);  // print statement 3
    }

    public static void main(String[] args) {
        Ideone a = new Ideone();
        System.out.println("object a "+a);    // print statement 1
        switchIt(a);
        System.out.println("object a after calling switchIt() "+a); // print statement 4
    }
}

Output:

輸出:

object a Ideone@106d69c
Object t Ideone@106d69c
object t after changing t Ideone@52e922
object a after calling switchIt() Ideone@106d69c

print statement 1,2,4 have same hash code but 3 has different hash code.

print語句1,2,4具有相同的哈希碼,但是3具有不同的哈希碼。


1. Creating object a

1.創建對象a


creating object a


2. Passing a to switchIt(Ideone t):

2.傳遞給switchIt(Ideone t):


Paasing a to switchIt()


3. Changing t to new Ideone():

3.將t更改為新的Ideone():


changing t to new value

Note:The hash code are not actual memory location.

注意:哈希碼不是實際的內存位置。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/09/23/72a34e60b8212404930b5a10f36e86fd.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com