2015-04-28 14 views
6

Tôi có 2 loại sau đây:Việc gán đối tượng Java có nghĩa là gì?

class Animal { 
    public static void staticMethod(int i) { 
     System.out.println("Animal : static -- " + i); 
    } 

    public void instanceMethod(int i) { 
     System.out.println("Animal : instance -- " + i); 
    } 
} 

class Cat extends Animal { 
    public static void staticMethod(int i) { 
     System.out.println("Cat : static -- " + i); 
    } 

    public void instanceMethod(int i) { 
     System.out.println("Cat : instance -- " + i); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.staticMethod(1);      // Cat : static -- 1 
     myCat.instanceMethod(2);      // Cat : instance -- 2 
     System.out.println(""); 

     Animal myAnimal = myCat; 
     Animal.staticMethod(3);      // Animal : static -- 3 
     myAnimal.staticMethod(4);     // Animal : static -- 4 [ ? ] 
     System.out.println(""); 

     myAnimal.instanceMethod(5);     // Cat : instance -- 5 
    } 
} 

Và khi tôi chạy Cát, tôi có kết quả như sau:

Cat : static -- 1 
Cat : instance -- 2 

Animal : static -- 3 
Animal : static -- 4 

Cat : instance -- 5 

tôi có thể hiểu 1,2,3 và 5, nhưng tại sao # 4 không phải là: "Mèo: tĩnh - 4"? Sự hiểu biết của tôi sẽ như sau:

myAnimal = myCat có nghĩa là "myAnimal" bây giờ giống y như "myCat", vì vậy bất kỳ nơi nào "myAnimal" sẽ xuất hiện, bạn có thể thay thế bằng "myCat" và nhận kết quả tương tự, bởi vì mọi thứ bên trong myAnimal giống như mọi thứ bên trong myCat, do đó "myAnimal.staticMethod (4)" phải giống như "myCat.staticMethod (4)" và đầu ra phải là: "Cat: static - 4", tương tự để "myCat.staticMethod (1)" ở trên.

Nhưng điều đó dường như không đúng, tại sao?

+0

Đây là nhật thực cho tôi biết: 'Phương thức tĩnh staticMethod (int) từ loại Animal nên được truy cập theo cách tĩnh' vì nó là phương thức tĩnh, nó chỉ bị ràng buộc với bố mẹ khi bạn gọi obj của nó là 'Động vật'. –

+0

thống kê được liên kết tại thời gian biên dịch. Đó là những gì ngăn cản họ bị lật đổ – njzk2

+0

Một câu hỏi trùng lặp của nó được hỏi xung quanh nhiều lần – madz

Trả lời

2

Từ Oracle docs:

8.4.8.2. Ẩn (bằng phương pháp lớp)

Nếu một lớp C tuyên bố hoặc được thừa hưởng một phương pháp m tĩnh, sau đó m được cho là ẩn bất kỳ phương pháp m', nơi mà các chữ ký của m là một subsignature (§8.4.2) chữ ký của m ', trong các siêu lớp và siêu kết nối của C mà nếu không sẽ có thể truy cập được để mã trong C.

Ví dụ 8.4.8.2-1. Gọi các phương thức lớp ẩn

Phương thức lớp (tĩnh) bị ẩn có thể được gọi bằng cách sử dụng tham chiếu có loại thực sự chứa khai báo của phương pháp. Về mặt này, việc ẩn các phương thức tĩnh khác với các phương thức ghi đè.Ví dụ:

class Super { 
      static String greeting() { return "Goodnight"; } 
      String name() { return "Richard"; } 
     } 
     class Sub extends Super { 
      static String greeting() { return "Hello"; } 
      String name() { return "Dick"; } 
     } 
     class Test { 
      public static void main(String[] args) { 
       Super s = new Sub(); 
       System.out.println(s.greeting() + ", " + s.name()); 
      } 
     } 

sản xuất đầu ra:

Goodnight, Dick

vì gọi trình chúc mừng sử dụng các loại s, cụ thể là siêu, để tìm ra, lúc biên dịch thời gian, mà phương thức lớp để gọi, trong khi việc gọi tên sử dụng lớp của s, cụ thể là Sub, để tìm ra, tại thời gian chạy, mà phương thức thể hiện để gọi.

2

Lý do là Java giải quyết các phương thức tĩnh dựa trên loại biến tham chiếu, và không đa hình tại thời gian chạy, như xảy ra với các phương thức mẫu.

Để mở rộng một chút, khi bạn đang thực hiện Animal myAnimal = myCat, bạn sẽ chỉ định tham chiếu Mèo cho tham chiếu Động vật. Điều này có thể chấp nhận được, bởi vì Cat cũng là một số Animal, vì vậy, bất kỳ thứ gì mà số Animal cũng có thể làm, một số Cat cũng có thể thực hiện được.

Hơn nữa, nếu bạn gọi một thể hiện (có nghĩa là, không tĩnh) phương pháp thông qua myAnimal tham khảo, và phương pháp này là overriden trong Cat thì phiên bản Cat của phương pháp này được gọi là, bởi vì đó là lý do tại sao phương pháp này đã được overriden trong nơi đầu tiên. Phương pháp tĩnh, mặt khác, không bao giờ được overriden. Đó là lý do tại sao chúng "tĩnh", như trong "phi động". Có nghĩa là các phương thức tĩnh có thể được giải quyết bằng trình biên dịch thay vì phải dựa vào môi trường thời gian chạy.

3

Bạn khai báo myAnimalAnimal. Do đó một phương thức tĩnh được gọi từ lớp đó.

Bạn không bao giờ nên gọi các phương thức tĩnh (hoặc truy cập các trường tĩnh) từ một cá thể để ngăn chặn loại nhầm lẫn này.

1

tĩnh nghĩa chính xác rằng: cuộc gọi được giải quyết tĩnh (trong trường hợp của bạn, nó được giải quyết dựa trên loại tuyên bố của biến, và biến là một thực thể compile-time).

Kết quả bạn mong đợi sẽ yêu cầu cuộc gọi được giải quyết động (đa hình, dựa trên loại thực tế của cá thể được tham chiếu và cá thể là thực thể thời gian chạy).

1

Khi bạn đặt myAnimal = myCat, con trỏ myAnimal trỏ đến đối tượng con mèo, nhưng khi bạn cố gắng truy cập phương thức tĩnh thông qua con trỏ myAnimal, nó truy cập phương thức tĩnh từ lớp mà myAnimal được khai báo là.

Các vấn đề liên quan