Khởi tạo nhiều đối tượng giống nhau


8

Điều gì chính xác xảy ra trong Java khi bạn khởi tạo cùng một đối tượng nhiều lần?

Ví dụ:

Test test = new Test();

sau đó tôi sẽ gọi nó một lần nữa, Test test = new Test();một lần nữa hoặc bên trong một vòng lặp. Việc khởi tạo trước đó sẽ được xử lý?

Câu trả lời:


16
  1. mỗi cuộc gọi new Test()tạo ra một thể hiện đối tượng mới của Testlớp
  2. test = new Test();gán tham chiếu của đối tượng đó cho biếntest
  3. Một câu lệnh lặp lại test = new Test()tạo ra một thể hiện thứ hai Testvà gán lại tham chiếu cho biến testđó, vì vậy tham chiếu đầu tiên được thay thế.

Tuy nhiên, nếu và khi lần khởi tạo đầu tiên sẽ được xử lý, tuy nhiên, tùy thuộc. Môi trường thời gian chạy Java theo dõi các tham chiếu, miễn là có bất kỳ tham chiếu nào đến một đối tượng đang sử dụng, đối tượng sẽ không được xử lý. Ví dụ: nếu giữa bước 2 và bước 3, tham chiếu đến lần khởi tạo đầu tiên được lưu trữ ở một nơi khác (như Test test2 = test;) và biến đó vẫn nằm trong phạm vi khi bước 3 xảy ra, thì đối tượng đầu tiên không được xử lý, vì test2vẫn giữ tham chiếu với nó Tuy nhiên, khi không có tuyên bố như vậy và bước 3 bỏ qua tham chiếu một và duy nhất đến đối tượng đầu tiên, thì việc loại bỏ đối tượng đó sẽ xảy ra.

Lưu ý rằng bản thân việc xử lý không xảy ra ngay lập tức, nhưng đôi khi muộn hơn, lần sau khi trình thu gom rác được chạy. Nhưng đó là độc lập với ngữ nghĩa của mã được thảo luận, đó chỉ là một câu hỏi về bộ nhớ và hiệu suất.


4
JVM không thực hiện đếm tham chiếu. Nói một cách chính xác, thông số kỹ thuật không bắt buộc cách thức (hoặc thậm chí là) bộ sưu tập rác được triển khai, nhưng tất cả các JVM chính sử dụng một số loại trình thu thập dấu vết.
Michael Borgwardt

@MichaelBorgwardt: đã thay đổi câu trả lời của tôi do nhận xét của bạn.
Doc Brown

if between step 2 and step 3 the reference to the first instantiation is stored somewhere else (like Test test2 = test;), and that variable is still in scope when step 3 occurs...Điều này có phần mang tính mô phạm nhưng bộ sưu tập rác không dựa trên phạm vi, mà dựa trên khả năng tiếp cận. Có thể một biến nằm trong phạm vi, nhưng giá trị của nó không còn được sử dụng nữa và giá trị đó có thể là rác được thu thập. Người thu gom rác không có phạm vi thuận tiện để đưa ra quyết định dựa trên điều đó.
Doval

@Doval: Tôi đồng ý, nhận xét này mang tính mô phạm ;-)
Doc Brown

5

1: Một số từ ngữ: Chúng tôi không khởi tạo các đối tượng, chúng tôi khởi tạo các lớp và sản phẩm của một khởi tạo lớp là một đối tượng (còn được gọi là một thể hiện). Tất nhiên chúng ta có thể khởi tạo một lớp nhiều lần theo yêu cầu để tạo một đối tượng mới và khác nhau với mỗi lần khởi tạo.

2: Sao cũng được, bạn không thể có mã bạn đề xuất:

Test test = new Test();
Test test = new Test();

không bạn có thể có điều này:

for (i=0; i<3; i++) {
    Test test = new Test();
    Test test = new Test();
}

Không có gì sẽ biên dịch, vì phần Test testnày là khai báo biến test(loại Test) và không có ngôn ngữ nào, kể cả Java, cho phép khai báo hai lần cùng một biến trong cùng một phạm vi.

Tuy nhiên, bạn có thể gán nhiều lần cho cùng một biến (như tên ngụ ý), với các đối tượng khác nhau, như thế này:

Test test = new Test();
test = new Test();

Dòng đầu tiên khai báo testvà gán cho nó một đối tượng mới được tạo. Dòng thứ hai gán cho testmột đối tượng khác, cũng mới được tạo.

Cũng lưu ý rằng các phím tắt được cho phép trong Java:

for (i=0; i<3; i++) {
    Test test = new Test();
}

Vòng lặp này sẽ không khai báo test3 lần. Nó được hiểu là gán ba đối tượng khác nhau mới theo thứ tự cho biến testsẽ chỉ được khai báo một lần. (so sánh với vòng lặp trước).

3: Điều gì xảy ra với biến testvà hai đối tượng cùng loại Test?

Biến testđầu tiên được gán tham chiếu của một đối tượng, sau đó của một đối tượng khác. Một biến chỉ giữ lại tham chiếu cuối cùng được gán.

Đối tượng đầu tiên của loại Testkhông được gán cho testnữa. Nếu không có biến nào khác được gán tham chiếu của nó, thì đối tượng này không thể được truy cập theo bất kỳ cách nào bởi chương trình, và do đó là vô ích. Nó được thực hiện đủ điều kiện để thu gom rác bởi hệ thống. Tại một số thời điểm, hệ thống (JVM) sẽ chạy trình thu gom rác của nó, nó sẽ xóa nó khỏi bộ nhớ.

Đối tượng thứ hai sẽ sống miễn là có ít nhất một biến tham chiếu đến nó, sau đó trình thu gom rác cũng sẽ chăm sóc nó và đưa nó đến Nghĩa trang đối tượng không được ước tính. Đó là cuộc sống thực sự của các đối tượng Java :-(


Tôi tình cờ tìm thấy lỗi đó trong một lớp học. Các lớp có một thuộc tính được khai báo là: WindowManager wm = new WindowsManager (); và sau đó một phương thức trong đó lập trình viên đang sử dụng thuộc tính này nhưng đã viết nhầm: WindowManager wm = new WindowsManager (); lần nữa. Nó không chỉ được biên dịch, mà còn chạy !! Không có cảnh báo nào và tất nhiên ứng dụng, là một thử nghiệm, đã không hoạt động tốt. Sau đó, tôi nhận ra nó đang tạo đối tượng trong phạm vi phương thức và thuộc tính không bao giờ được sửa đổi. Vì vậy, hãy cẩn thận
Ricker Silva

1
Như bạn đã giải thích một cách hoàn hảo, đây không phải là sự gán lại của cùng một biến. Một lỗi đổ bóng tương tự có thể xảy ra khi sử dụng một tham số nếu bạn quên thistừ khóa, như trong các hàm tạo : this.name = name.
phút

-1

Câu trả lời ngắn: tất cả các đối tượng được tạo trước đó sẽ bị loại bỏ nếu không có ai chỉ vào chúng. Chỉ có cái gần đây nhất sẽ tồn tại bởi vì thử nghiệm tham chiếu nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.