Hỏi về Reference Variable Type trong Java

Hi mọi người,
Để hiểu sâu hơn về Java, mình sẽ post 1 số câu hỏi về Java cho mọi người thảo luận.
Mình có đoạn code sau:

class Animal {
}

class Horse extends Animal {
	public void run() {
		System.out.println("Horse Run");
	}
}


class TestAnimal {
	public static void main (String[] args) {
		Animal animal = new Horse();
		animal.run();
	}
}

Câu hỏi: Kết quả của hàm main() trong class TestAnimal là gì?
P/S: các bạn trả lời và giải thích tại sao nhé :). Tốt nhất không nên copy code chạy thử :smiley:

4 Likes

ra dòng này
“Horse Run”

2 Likes

Báo lỗi vì trong Animal không có method run(). Muốn fix thì phải ép kiểu trực tiếp.

1 Like

Reference Variable: Hình như cái này có vẻ như là không có nhiều liên quan lắm…

1 Like

compile error :smile: cái này là static binding và dynamic binding trong java. animal có reference type là Animal, object type là Horse. Lúc compile lớp Animal không có method run() nên sẽ sinh ra lỗi :blush:

1 Like

cái này như kiểu là class Cha không thể gọi phương thức của class Con, nhưng class Con lại gọi được phương thức ở class Cha !

1 Like

Hehe, @GDGHN_AndroidTeam, @Dreamer094@kien8995 trả lời đúng:
Compile Error

Mình giải thích rõ hơn:

Animal animal = new Horse();

Lệnh này sẽ tạo ra 2 Variable:

  • ***new Horse()***; tạo ra 1 object variable lưu trong bộ nhớ.

  • animal là một reference variable (như con trỏ trong C++) giá trị của nó chính là địa chỉ bộ nhớ Object horse ở trên. Kiểu của animal là Animal chứ không phải là Horse.

    animal.run();

Lệnh này sẽ gọi đến method run() của Object mà animal (Reference variable) trỏ đến. Nhưng trước khi vào quá trình Runtime, Compiler không hiểu được hàm run bởi vì kiểu của animal là Animal, mặc giù Object của nó là Horse.

Nếu các bạn sửa 1 chút:

class TestAnimal {
	public static void main (String[] args) {
		Animal animal = new Horse();
		((Horse)animal).run();
	}
}

Bạn đã ép kiểu của Reference variable từ Animal thành Horse, và nó sẽ hiểu được hàm run(); -> compile pass.

10 Likes

Cách hiểu của @Dreamer094 là 1 cách hay để nhớ, nhưng đấy chỉ là ở mức biết, còn hiểu tại sao thì bạn sẽ nhớ lâu hơn.

cảm ơn bạn đã góp ý !

1 Like

Sao cái này lại lấy tiêu đề là Reference Variable ?

Bạn đọc câu trả lời của mình nhắc đến rất nhiều Reference Variable, rất nhiều người code java mà không hiểu nó là gì đó.
Bản chất của câu hỏi này là hiểu rõ Reference Variable là gì :slight_smile:

Thế sao không để animal có kiểu Horse từ đầu mà phải để Animal rồi lại ép sang Horse ạ? :smile:

1 Like

Đấy là mục đích sử dụng tinh kế thừa inheritance, còn đây chỉ là ví dụ của trường hợp này thôi bạn.
bạn có thể đọc bài Object Orientation để hiểu rõ hơn nhé.

Em cũng đọc topic đó rồi nhưng vẫn còn lơ mơ quá :smile: anh cho em xin một ví dụ thực tế mà cần phải khai báo kiểu “cọc cạch” như thế này được k ạ :smile:

1 Like

Thực tế sau nàu bạn đi làm, tham gia 1 dự án nào đó về java sẽ gặp rất nhiều trường hợp này. Java sinh ra để đáp ứng nhu cầu của các hệ thống cực lớn như ngân hàng, quản trị doanh nghiệp… Vì thế nó phải rất chặt chẽ, chính là tuân thủ OOP.
Còn đây là các ví dụ trương trình nhỏ, để bạn học cơ bản. Chứ không có mục đích sử dụng nào ở đây cả :d. Hi vọng bạn hiểu ý mình.
Lời khuyên của mình là bạn nên đọc Book pdf mà mình đính kèm ở topic, rất đầy đủ.

1 Like

Theo quan điểm của mình thì bạn đang hiểu sai ý nghĩa của khái niệm Reference Variable. Khái niệm này nhằm ám chỉ cách thức tổ chức cửa biến trên ô nhớ nhằm phân biệt việc một biến lưu trữ địa chỉ của ô nhớ nhằm mục đích tham chiếu đến giá trị được ô nhớ đó lưu trữ với cả cách biến lưu trữ ngay một giá trị có kiểu dữ liệu nguyên thủy.

Cái trên của bạn chỉ hợp lí khi đưa ra ví dụ của kế thừa. Với Reference Variable ngày ta hãy có những bài toán như sau:

public static void main(String args){
    A a = new A();
    a.b = "c";
    change(a);
    notChange(a);
    print a;
}

private static void change(A a){
    a.c = "d";
}

private static void notChange(A a){
    a = new A();
    a.b = "e";
}
3 Likes

Ý kiến của mình như bạn ở trên.
Thực ra ví dụ trên đang dùng biến con trỏ chứ k phải tham chiếu.
Biến tham chiếu là biến tham chiếu trực tiếp đến vùng nhớ của biến. Ví dụ trên ta đang tham chiếu đến 1 đối tượng Horse thông qua 1 con trỏ Animal. Việc run() không được bởi vì đọc vùng nhớ theo kiểu của Animal.

1 Like

Theo định nghĩa thì " Animal animal = new Horse( )": thực chất chỉ tạo ra một biến tham chiếu animal có kiểu Animal trỏ đến đối tượng Horse () có kiểu Horse. Bản chất của nó giống như một biến con trỏ trong C++. Java là một ngôn ngữ kiểu chặt nên trong câu lệnh này đã Gán sai kiểu giá trị cho một biến dẫn đến lỗi biên dịch. Chính vì vậy mà ta cần phải ép kiểu dữ liệu cho nó: “((Horse) animal).run()” .Cho nên ý của chủ thớt muốn mọi người hiểu rõ hơn biến tham chiếu (Reference Variable).

1 Like

Theo quan điểm của mình thì bạn đang hiểu sai ý nghĩa của khái niệm Reference Variable. Khái niệm này nhằm ám chỉ cách thức tổ chức cửa biến trên ô nhớ nhằm phân biệt việc một biến lưu trữ địa chỉ của ô nhớ nhằm mục đích tham chiếu đến giá trị được ô nhớ đó lưu trữ với cả cách biến lưu trữ ngay một giá trị có kiểu dữ liệu nguyên thủy.

Nói thật là tớ đọc mãi vẫn không hiểu ý của bạn lắm :smile:, còn cái ví dụ của bạn đúng là ví dụ về Reference Variable, nhưng nó là 1 khía cạnh khác. Của mình nói về “Kiểu của Reference Variable”, luôn luôn là duy nhất (trong vd là Animal), định nghĩa 1 lần và không bao h thay đổi (ý là không bao h thành kiểu Horse). Mình sẽ sửa cái tiêu đề cho bạn đỡ confuse.

@dkstorm13 trong java không có khái niệm con trỏ, nó chính là Reference Variable, hiểu nó như con trỏ cũng không sai. Còn giải thích của bạn thì chuẩn 100% rồi :smile:

Tớ gửi 1 hình vẽ miêu tả rõ hơn về Reference Variable. Ví dụ của tớ để mọi người biết về Reference Variable, rất nhiều bạn không biết khái niệm này.

Riêng tớ sẽ có hẳn 1 phần nói về cái này trong topic Object Orientation, chắc chắn sẽ có Ví Dụ của bạn :smile:

4 Likes

Tóm lại cho dễ hiểu
Object type (Horse) sẽ quyết định overridden method tại thời điểm chạy (run time). Reference type (tức animal) sẽ quyết định hàm overloaded tại thời điểm compile time.
Code mẫu trên chủ thớt gọi animal.run() tức là đã gọi 1 reference type, compiler sẽ đi tìm run() của animal tại thời điểm compile time nhưng tiếc là kiếm đếch được nên sẽ la làng lên.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?