“Object truyền tham chiếu, primary truyền tham trị” đây là câu thần chú ắt hẳn rất nhiều lập trình viên đã đọc hay nghe qua khi học lập trình hướng đối tượng(OOP). Quên câu thần chú đó đi và hãy xem xét đoạn code dưới đây. Hãy suy đoán kết quả của dòng 9 và 12 nhé.

package java_pointer;

public class Main {

	public static void main(String[] args) {
		Foo f = new Foo("f");
		
        changeReference(f);
        f.log();
        
        modifyReference(f);
        f.log();
	}
	
	public static void changeReference(Foo a){
        Foo b = new Foo("b");
        a = b;
	}
	
	public static void modifyReference(Foo c){
        c.setName("c");
	}
	
	static class Foo{
		
		private String mName;
		
		public Foo(String name){
			mName = name;
		}
		
		public void setName(String name){
			mName = name;
		}
		
		public void log(){
			System.out.println("ten toi la: "+ mName);
		}
	}
}

Bạn đã đoán ra kết quả chưa? kết quả của bạn có giống như ở dưới. Nếu không giống hãy copy đoạn code ở trên và chạy thử để kiểm chứng.

ten toi la: f
ten toi la: c

Tại sao lại như vậy? tạo sao không phải là “b” mà lại là “f”. Câu trả lời là vì Java không có kiểu truyền tham chiếu. Nhiều người thường nghĩ rằng Java là ngôn ngữ thuần hướng đối tượng, Java không có con trỏ nhưng thực ra ở bên trong vẩn còn tồn tại con trỏ, chẳng qua là nó đã bị che giấu đi. Mỗi khi chúng ta khởi tạo 1 đối tương vd “Foo f = new Foo(“f”)” thì f có thể được xem như là 1 con trỏ. Để chứng minh điều này chúng ta hãy tìm hiểu đoạn mã ban đầu đã hoạt động ra sao.

  1. Đầu tiên tại dòng code thứ 6
Foo f = new Foo("f");

Ở đây chúng ta khởi tạo 1 đối tượng  f có kiểu là Foo, truyền cho nó 1 cái tên là f.arXpP

2. Xem xét hàm “public static void changeReference(Foo a)”. một đối tượng a có Kiểu Foo được khai báo, nhưng không trỏ đến đâu(null)
k2LBD

3. Tại dòng số 8 changeReference(f) bởi vì chúng ta truyền f vào như 1 đối số nên a lúc này củng trỏ đến vùng nhớ tương tự f.

1Ez74

4. Dòng 16

Foo b = new Foo("b");

Khởi tạo đối tượng b kiểu Foo truyền cho nó 1 cái tên b.

Krx4N

5. Dòng 17

a = b;

Lúc này a sẽ trỏ đến vùng nhớ tương tự b(không phải f nhé). Vì vậy cho nên khi ra khỏi hàm changeReference tại dòng số 8 thì f không hề bị thay đổi, thuộc tính nName của nó vẩn là f.

rCluu

     6. dòng 11

modifyReference(f);

Tương tự như dòng số 9. 1 đối tượng c có kiểu Foo được tạo ra và trỏ tới cùng vùng nhớ như f.

PRZPg

    7. dòng 21

c.setName("c");

Vì c và f cùng trỏ đến cùng 1 vùng nhớ nên khi c thay đổi thì f củng thay đổi.

H9Qsf

  • Áp dụng đoạn code trên các ngôn ngữ như c#, c++ bạn sẽ thu được kết quả tương tự như chúng vừa xem. Vậy c#, c++ củng không có kiểu tham trị chăng? thực ra không phải vậy với c# chúng ta có khái niệm ref và out. Còn c++ chúng ta có thể dùng con trỏ giúp chúng ta truyền tham số dạng tham biến. Còn Java thì không có các khái niệm này.
Advertisements