Java Xử Lý Việc Khởi Tạo, Lưu Trữ và Thay Đổi Dữ Liệu Của Object Như Thế Nào
Tất cả các developer biết về ngôn ngữ Java đều hiểu cách để khởi tạo một object từ một class, công việc này rất đơn giản nhờ sử dụng từ khóa new: new MyNumber() Tùy vào method signature của class được sử dụng để tạo object chúng ta sẽ cần truyền vào một số lượng đối số (argument) nhất định. ...
Tất cả các developer biết về ngôn ngữ Java đều hiểu cách để khởi tạo một object từ một class, công việc này rất đơn giản nhờ sử dụng từ khóa new:
new MyNumber()
Tùy vào method signature của class được sử dụng để tạo object chúng ta sẽ cần truyền vào một số lượng đối số (argument) nhất định. Ví dụ với class MyNumber được định nghĩa như sau:
public MyNumber { public int counter; public MyNumber(init initialValue) { counter = initialValue; } }
Thì chúng ta có thể khởi tạo object từ class này với đối số truyền vào như sau:
MyNumber myNumber = new MyNumber(100);
Tuy nhiên bạn có biết điều gì thực sự diễn ra khi chạy đoạn code trên?
3 Sự Kiện Diễn Ra Khi Khởi Tạo Object
Có 3 sự kiện diễn ra khi chúng ta tạo một object từ class:
- Java (cụ thể là Java Virtual Machine) sẽ lấy ra một địa chỉ bộ nhớ còn trống trong memory để lưu trữ dữ liệu của object. Các biến trong đối tượng mới tạo ra này (gọi là instance variable hay field) được gán cho các giá trị mặc định nếu như chúng được khai báo mà chưa được gán giá trị.
- Tiếp theo Java sẽ gọi phương thức dựng (gọi là constructor method) với các đối số được sử dụng khi khởi tạo object. Ngoài ra các bước
- Cuối cùng Java sẽ trả về địa chỉ bộ nhớ trên RAM. Nếu như một biến được gán giá trị từ việc khởi tạo object thì Java sẽ gán giá trị của bộ nhớ này cho giá trị của biến đó.
OK tuy nhiên sẽ được lợi gì nếu như tôi hiểu về quy trình tạo object trên? Để trả lời câu hỏi trên chúng ta sẽ tham khảo một ví dụ sau:
MyNumber myNumber = new MyNumber(100); MyNumber newNumber = myNumber; newNumber.counter = 101;
Lúc này bạn đoán giá trị của myNewNumber.counter sẽ là bao nhiêu:
System.out.println(myNumber.counter);
Câu trả lời là 101 thay vì 100. Tại sao vậy?
Object Referrence
Nhớ lại 3 sự kiện diễn ra khi khởi tạo object đề cập trong phần trước bạn sẽ thấy lúc này giá trị của biến myNumber chính là giá trị của địa chỉ bộ nhớ của object khởi tạo. Do đó khi chúng ta gán giá trị của biến newNumber bằng với biến myNumber như sau:
MyNumber newNumber = myNumber;
Thì lúc này Java sẽ trỏ giá trị của biến newNumber về địa chỉ bộ nhớ RAM nơi lưu trữ dữ liệu của object. Hay nói cách khác myNumber và newNumber tham chiếu tới một địa chỉ duy nhất trên bộ nhớ.
Do đó khi bạn thay đổi giá trị của biến counter của object newNumber trong dòng code:
newNumber.counter = 101;
Thì lúc này dữ liệu thực tế bị thay đổi là dữ liệu nằm ở địa chỉ bộ nhớ lưu trữ dữ liệu của object (được sử dụng bởi cả myNumber và newNumber).
Tính năng trên trong Java được gọi là tham chiếu tới đối tượng hay object refference. Ở đây chúng ta nói biến newNumber giữ vai trò là một pointer tham chiếu tới địa chỉ trên RAM lưu trữ dữ liệu của object được khởi tạo trước đó (và gán cho giá trị của biến myNumber).
Bạn có thể tưởng tượng object giống như một màn hình hiển thị nội dung của một chương trình từ một kênh nào đó như HTV1. Các biến myNumber và newNumber giống như các remote điều khiển.
Bạn có thể sử dụng một trong hai remote điều khiển này để chuyển kênh và khi điều đó diễn ra thì màn hình sẽ chuyển sang kênh được thay đổi bởi một trong hai remote.
Derfeference
Điều gì diễn ra khi thay đổi giá trị của newNumber về một số integer, string hoặc object khác... ví dụ như sau:
int newNumber = 2017;
Liệu lúc này myNumber sẽ nhận giá trị là 2017 hay không?
Câu trả lời là không. Điều này là bởi vì khi bạn gán giá trị khác cho newNumber thì Java sẽ trỏ giá trị của biến này về một địa chỉ khác trên RAM trên đó lưu trữ dữ liệu mới của nó. Do đó biến myNumber không bị ảnh hưởng. Tính năng này còn được gọi là object derefference.
Giống như ví dụ ở trên điều gì xảy ra nếu như bạn làm rơi một chiếc remote và nó bị hư? Chiếc remote thứ hai vẫn không bị ảnh hưởng và nó vẫn có thể chuyển kênh.
Nói cách khác nếu bạn thay đổi giá trị của object tại địa chỉ ban đầu thì sự thay đổi này sẽ ảnh hưởng tới tất cả các biến trỏ tới object này (ở ví dụ của chúng ta là hai biến newNumber và myNumber).