CHÀO! Tôi nghĩ bạn sẽ không ngạc nhiên lắm nếu tôi nói với bạn rằng máy tính của bạn có dung lượng bộ nhớ hạn chế :)
Vòng đời của đối tượng - 1
Ngay cả ổ cứng của bạn (có kích thước gấp nhiều lần RAM) cũng có thể chứa đầy các trò chơi, chương trình TV yêu thích của bạn và những thứ khác. Để ngăn điều này xảy ra, bạn cần theo dõi trạng thái hiện tại của bộ nhớ máy tính và xóa các tệp không cần thiết. Làm thế nào để tất cả những điều này liên quan đến lập trình Java? Khá trực tiếp! Xét cho cùng, việc tạo bất kỳ đối tượng nào cũng khiến máy Java cấp phát bộ nhớ cho nó . Một chương trình lớn trong thế giới thực tạo ra hàng chục hoặc hàng trăm nghìn đối tượng và một đoạn bộ nhớ được phân bổ cho mỗi đối tượng. Nhưng bạn nghĩ sao, có bao nhiêu đối tượng trong số này tồn tại? Họ có "sống" trong khi chương trình của chúng tôi đang chạy không? Dĩ nhiên là không. Ngay cả với tất cả các ưu điểm của chúng, các đối tượng Java không phải là bất tử :) Các đối tượng có vòng đời riêng của chúng. Hôm nay chúng ta sẽ nghỉ viết mã một chút và khám phá quy trình này :) Việc hiểu cách thức hoạt động của một chương trình và quản lý tài nguyên cũng rất quan trọng. Vì vậy, cuộc sống của một đối tượng bắt đầu từ đâu? Giống như một con người, từ khi sinh ra, tức là khi nó được tạo ra.

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
Đầu tiên, máy ảo Java phân bổ bộ nhớ cần thiết để tạo đối tượng. Sau đó, nó tạo một tham chiếu đến nó (trong trường hợp của chúng ta là cat) để có thể theo dõi nó. Sau đó, tất cả các biến được khởi tạo, hàm tạo được gọi và đối tượng mới của chúng ta hiện đang sống cuộc sống của chính nó :) Thời gian tồn tại của đối tượng khác nhau. Không có số liệu chính xác ở đây. Trong mọi trường hợp, một đối tượng tồn tại trong chương trình và thực hiện các chức năng của nó trong một khoảng thời gian. Nói chính xác, đối tượng "còn sống" miễn là có các tham chiếu đến nó. Ngay khi không có tham chiếu, đối tượng "chết". Ví dụ:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
Trong main()phương thức này, đối tượng Xe hơi "Lamborghini Diablo" không còn tồn tại trên dòng thứ hai. Chỉ có một tham chiếu đến nó và tham chiếu được đặt thành null. Vì không còn tài liệu tham khảo nào về Diablo, nó trở thành "rác". Một tham chiếu không cần phải được đặt thành 0 để điều này xảy ra:

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
Ở đây chúng ta đã tạo một đối tượng thứ hai và gán nó cho tham chiếu lamborghini. Bây giờ có hai tham chiếu trỏ đến Lamborghini Gallardođối tượng, nhưng Lamborghini Diablođối tượng không có. Điều này có nghĩa là Diablođối tượng trở thành rác. Đây là lúc bộ thu gom rác tích hợp (GC) của Java bắt đầu hoạt động.
Vòng đời của đối tượng - 2
Trình thu gom rác là một cơ chế nội bộ của Java chịu trách nhiệm giải phóng bộ nhớ, tức là loại bỏ các đối tượng không cần thiết khỏi bộ nhớ. Có một lý do tại sao chúng tôi chọn đại diện cho nó bằng robot hút bụi. Trình thu gom rác hoạt động theo cùng một cách: nó "di chuyển" chương trình của bạn ở chế độ nền, thu gom rác. Bạn thực tế không phải tương tác với nó. Công việc của nó là xóa các đối tượng không còn được sử dụng trong chương trình. Do đó, nó giải phóng bộ nhớ cho các đối tượng khác. Bạn có nhớ rằng ở phần đầu của bài học, chúng tôi đã nói trong cuộc sống thực, bạn phải theo dõi trạng thái máy tính của mình và xóa các tệp cũ không? Nếu chúng ta đang nói về các đối tượng Java, thì bộ thu gom rác sẽ làm việc này cho bạn. Bộ thu gom rác được khởi động nhiều lần khi chương trình của bạn chạy: bạn không cần phải gọi nó một cách rõ ràng và ra lệnh cho nó (mặc dù điều này là có thể về mặt kỹ thuật). Chúng ta sẽ nói nhiều hơn về trình thu gom rác sau và phân tích cách thức hoạt động của nó chi tiết hơn. Khi bộ thu gom rác tiếp cận một đối tượng—ngay trước khi nó bị hủy—phương thức đặc biệt của đối tượng finalize()được gọi. Phương thức này có thể được gọi để giải phóng một số tài nguyên bổ sung được sử dụng bởi đối tượng. Phương finalize()thức thuộc về lớp Object. Nói cách khác, nó tương tự với equals(), hashCode()toString()(mà bạn đã gặp trước đây). Mỗi đối tượng có nó . Nó khác với các phương pháp khác ở chỗ...chúng ta nên nói thế nào đây...nó rất cố ý. Bằng cách đó chúng tôi có nghĩa lànó không phải lúc nào cũng được gọi trước khi một đối tượng bị hủy . Lập trình là một hoạt động rất chính xác. Lập trình viên yêu cầu máy tính làm một việc gì đó và máy tính sẽ làm việc đó. Tôi cho rằng bạn đã quen với kiểu hành vi này, vì vậy ban đầu bạn có thể khó chấp nhận ý tưởng sau: "Trước khi một đối tượng bị hủy, phương thức của lớp Đối tượng được gọi. Hoặc không. finalize()Nếu chúng ta gặp may! " Tuy nhiên, đây là thực tế. Máy Java tự xác định xem có nên gọi finalize() theo từng trường hợp hay không. Để thử nghiệm, hãy thử chạy đoạn mã sau:

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
Chúng tôi tạo một Catđối tượng và trong dòng tiếp theo, chúng tôi loại bỏ tham chiếu duy nhất đến nó. Và chúng tôi làm điều đó một triệu lần. Chúng tôi đã ghi đè rõ ràng finalize()phương thức. Mỗi khi một Catđối tượng bị phá hủy, nó phải hiển thị một chuỗi—tổng cộng một triệu lần. Nhưng không! Nói chính xác, trên máy tính của tôi, nó chỉ được thực hiện 37346 lần! Nói cách khác, máy Java của tôi đã quyết định finalize()chỉ gọi phương thức này trong 1 trong số 27 trường hợp. Trong các trường hợp khác, việc thu gom rác không liên quan đến cuộc gọi này. Hãy thử tự chạy mã này. Bạn rất có thể sẽ nhận được một kết quả khác. Như bạn có thể thấy, thật khó để gọi finalize()một đối tác đáng tin cậy :) Vì vậy, đây là một mẹo nhỏ cho tương lai: đừng dựa vào finalize()phương pháp giải phóng các tài nguyên quan trọng.JVM có thể gọi nó hoặc có thể không. Ai biết? Nếu đối tượng của bạn nắm giữ một số tài nguyên quan trọng về hiệu suất (ví dụ: kết nối cơ sở dữ liệu mở) khi nó còn hoạt động, thì tốt hơn là tạo và gọi rõ ràng một phương thức đặc biệt để giải phóng chúng khi đối tượng không còn cần thiết. Bằng cách đó, bạn sẽ biết chắc chắn rằng hiệu suất của chương trình sẽ không bị ảnh hưởng. Chúng tôi đã bắt đầu bằng cách nói rằng làm việc với bộ nhớ và thu gom rác là những chủ đề rất quan trọng và thực tế là như vậy. Xử lý sai tài nguyên và hiểu sai cách dọn dẹp các đối tượng không cần thiết có thể dẫn đến một trong những lỗi khó chịu nhất: rò rỉ bộ nhớ . Đây là một trong những lỗi lập trình nổi tiếng nhất. Nó thậm chí còn có bài viết Wikipedia của riêng mình. Mã được viết kém có thể tạo ra tình huống trong đó bộ nhớ được phân bổ mỗi lần cho các đối tượng mới được tạo, nhưng các đối tượng cũ, không cần thiết sẽ không có sẵn để thu gom rác. Vì chúng ta đã tạo ra sự tương tự của rô-bốt hút bụi, hãy tưởng tượng điều gì sẽ xảy ra nếu trước khi vận hành rô-bốt, bạn rải tất khắp nhà, đập vỡ một chiếc bình thủy tinh và để các mảnh Lego vương vãi khắp sàn. Đương nhiên, rô-bốt sẽ cố gắng làm điều gì đó, nhưng một ngày nào đó nó sẽ bắt kịp.
Vòng đời của đối tượng - 3
Để máy hút bụi hoạt động bình thường, bạn cần giữ cho sàn nhà ở tình trạng tốt và nhặt mọi thứ mà nó không thể xử lý được. Bộ thu gom rác tuân theo nguyên tắc tương tự. Nếu một chương trình có nhiều đối tượng mà nó không thể dọn sạch (chẳng hạn như một chiếc tất hoặc Lego cho máy hút bụi rô-bốt của chúng ta), một ngày nào đó chúng ta sẽ hết bộ nhớ. Không chỉ chương trình của bạn bị treo mà tất cả các chương trình khác đang chạy trên máy tính cũng vậy. Rốt cuộc, họ cũng sẽ không có đủ bộ nhớ (quay trở lại phép loại suy của chúng ta, mảnh kính vỡ trên sàn không chỉ dừng máy hút bụi mà còn cả những người sống trong nhà). Tóm lại, đây là vòng đời của đối tượng và bộ sưu tập rác trong Java. Bạn không cần phải ghi nhớ điều này: chỉ cần hiểu cách thức hoạt động của nó là đủ. Trong bài học tiếp theo, chúng tôi' sẽ trở lại các quá trình này một cách chi tiết hơn. Nhưng hiện tại, bạn có thể quay lại giải quyết các nhiệm vụ CodeGym :) Chúc may mắn!