30/09/2018, 17:42

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ử

vũ xuân quân viết 19:45 ngày 30/09/2018

ra dòng này
“Horse Run”

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.

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

kien tran viết 19:53 ngày 30/09/2018

compile error 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

Nguyễn Hữu Nghĩa viết 19:44 ngày 30/09/2018

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 !

Cương Nguyễn viết 19:49 ngày 30/09/2018

Hehe, @GDGHN_AndroidTeam, @Dreamer094 và @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.

Cương Nguyễn viết 19:49 ngày 30/09/2018

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.

Nguyễn Hữu Nghĩa viết 19:53 ngày 30/09/2018

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

Truong Pham viết 19:48 ngày 30/09/2018

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

Cương Nguyễn viết 19:58 ngày 30/09/2018

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ì

Thành Phạm viết 19:55 ngày 30/09/2018

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

Cương Nguyễn viết 19:47 ngày 30/09/2018

Đấ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é.

Như đã trình bày ở http://daynhauhoc.com/t/to-chuc-hoc-core-java/10176 Mình xin bắt đầu với topic đầu tiên: Object Orientation(OO) trong java. Trước khi bắt đầu mình có 1 vài chú ý nho nhỏ smile: Rất nhiều từ mình sẽ không dịch sang tiếng việt mà giữ nguyên tiếng anh VD: Object, Class, Encapsulation... Vì sao lại thế chắc các bạn cũng hiểu. Không thảo luận những vấn đề không liên quan đến topic: VD: đang nói về Object Orientation lại có bạn hỏi về Exception, Thread... Những đóng góp ý kiến, c…

Thành Phạm viết 19:42 ngày 30/09/2018

Em cũng đọc topic đó rồi nhưng vẫn còn lơ mơ quá 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 ạ

Cương Nguyễn viết 19:53 ngày 30/09/2018

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 đủ.

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";
}
Bao "Storm" Le viết 19:52 ngày 30/09/2018

Ý 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.

Truongmta viết 19:56 ngày 30/09/2018

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).

Cương Nguyễn viết 19:54 ngày 30/09/2018

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 , 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

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

minh tran viết 19:47 ngày 30/09/2018

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.

Bao "Storm" Le viết 19:58 ngày 30/09/2018

Mình cũng hiểu ý bạn.
Ý mình tức là thế này: Chúng ta có 1 biến kiểu Animal để lưu trữ địa chỉ của đối tượng của class Horse, và biến kiểu Animal này là biến tham chiếu, khi tham chiếu đến biến animal ta sẽ được địa chỉ của đối tượng của class Horse. Mà thực chất thì biến animal chính là 1 con trỏ đang trỏ đến đối tượng Horse.
Về việc tại sao lại gọi run() báo lỗi, theo mình nghĩ như này:

  • Đối tượng của class Animal sẽ lưu trữ 100 bytes (giả dụ).
  • class Horse kế thừa từ class Animal nên nó sẽ kế thừa 100 bytes của class Animal và nó có thêm 50 bytes riêng của nó (vì nó có thêm phương thức run()).
  • Bởi vì biến animal có kiểu Animal nên biến animal chỉ đọc được 100 bytes của đối tượng của class Horse, và trong 100 bytes đó không có phương thức run() nên nó không thực hiện được.
    Mình biết ít nên có gì pro sửa giúp. Thanks
Bài liên quan
0