2013-04-24 41 views
19

Dưới đây tôi có hai lớp.Parent và Child. Lớp Child thừa hưởng từ lớp Parent. Trong constructor của lớp Parent, tôi đang gọi phương thức print() của lớp Parent.Các phương thức gọi bên trong Constructor

Khi tôi tạo đối tượng cho lớp con trong phương thức main(), hàm khởi tạo lớp cha và phương thức lớp con() được gọi thay vì phương thức print class() của lớp cha.

Q1. Tại sao điều này xảy ra.

Q2. Tại sao giá trị của i là 0

public class Sample 
{ 
    public static void main(String[] args) 
    { 
     Child objChild = new Child(); 
     objChild.print(); 
    } 
} 

class Parent 
{ 
    void print() 
    { 
     System.out.println("i Value"); 
    } 

    Parent() 
    { 
     print(); 
    } 
}  

class Child extends Parent 
{ 
    int i = 45; 

    void print() 
    { 
     System.out.println("i Value = "+i); 
    } 
} 

OP

i Value = 0 
i Value = 45 
+0

Nếu tôi thay thế print() với this.print() trong constructor cha tại sao nó không in "i Value"? – user3218743

Trả lời

19

Lý do mà phương thức con được gọi là do công văn ảo là tiêu chuẩn trong Java. Khi bạn gọi phương thức, nó quyết định phương thức nào thực sự gọi khi chạy dựa trên kiểu thực tế của đối tượng.

Vì lý do tại sao nó in 0, đó là vì i chưa được đặt thành 45. Mỗi trường được khởi tạo với giá trị mặc định cho loại đó, 0 trong trường hợp số nguyên. Khi bạn viết int i = 45, trình biên dịch sẽ tạo mã trong hàm tạo để đặt i = 45. Nhưng nó đặt mã này sau khi hàm tạo mẹ được gọi. Vì vậy, bạn đang in biến trước khi nó được khởi tạo với giá trị dự định của nó.

+0

Cảm ơn bạn đã trả lời Điều duy nhất tôi vẫn chưa rõ ràng là mã trong Parent Class Constructor đầu tiên được đánh giá trước khi bất kỳ mã nào trong child child được thực hiện. Trong trường hợp này, phương thức call to print() được tạo trong constructor code trong lớp con sẽ không có sẵn trong hàm tạo hàm lớp cha. Plz sửa tôi nếu tôi sai –

1

con Your first gọi constructor của cha mẹ bạn. Tại thời điểm này, tôi không được khởi tạo với giá trị 45. Đó là lý do tại sao nó in 0 (giá trị int mặc định).

2

Bởi vì lúc đó thời gian của cuộc gọi đầu tiên phương pháp in i không được khởi tạo đến 45 để nó in 0.
cuộc gọi đi như thế

  • constructor đứa trẻ này (như vì constructor chaining được kết từ con để mẹ)
  • hàm tạo mẹ
  • phương thức in (hiện tại đây i không được khởi tạo hàm tạo con coz chưa hoàn thành để in giá trị mặc định là i là 0)
  • nay sau khi hoàn thành xây dựng phụ huynh và sau đó xây dựng con i được giá trị của nó mà là 45-
  • vì vậy bây giờ nó in 45 trên cuộc gọi tiếp theo của phương pháp in
+1

Vui lòng sử dụng đúng chính tả và định dạng để dễ đọc. – Antimony

+0

@Antimony đã chỉnh sửa và định dạng – exexzian

+0

@Antimony nhưng tại sao downvote - câu trả lời của tôi không sai – exexzian

2

Thứ nhất, tôi không thấy các nhà xây dựng định nghĩa trong lớp Child của bạn.

Khi bạn không định nghĩa một constructor cho một lớp Child, constructor mặc định của nó là:

public Child() { 
    super(); 
} 

đâu super(); gọi Parent lớp constructor (siêu constructor lớp).

Tuy nhiên, bạn định nghĩa phương pháp print() của bạn trong Child lớp, và vì nó có cùng một chữ ký (tên + tham số) là phương pháp trong Parent lớp, nó sẽ ghi đè phương thức lớp siêu của nó với cùng một chữ ký.

Đó là lý do tại sao các cuộc gọi lớp Child của bạn là Parent trình tạo lớp, trong khi nó gọi phương thức print() của riêng nó.

-Nhập:

Giá trị i đầu tiên là 0 vì bạn đã không khởi tạo một int biến i trong Parent lớp, và giá trị của một biến int chưa được khởi tạo là 0 theo mặc định. Sau Parent được gọi, nó bây giờ Child 's gọi print() phương pháp, và i được khởi tạo trong Child lớp, vì vậy bây giờ i là giá trị mà bạn khởi tạo

+0

Để OP: 'Cảm ơn bạn đã trả lời Điều duy nhất tôi vẫn chưa rõ ràng là mã trong Parent Class Constructor đầu tiên được đánh giá trước khi bất kỳ mã nào trong child child được thực hiện.' -> Bạn nên định nghĩa một hàm tạo lớp Con theo cách thủ công. – user25409

+0

Không cần phải định nghĩa một hàm tạo theo cách thủ công nếu hàm tạo mặc định thực hiện những gì bạn muốn. Vấn đề ở đây là trực giao - bạn đang phá vỡ một quy ước chung trong Java bằng cách gọi một phương thức ghi đè trong hàm tạo siêu lớp. Vì điều này mở ra cho bạn những hành vi bất ngờ, nó thường không được khuyến khích. – Antimony

+0

@Antimony: Tôi đoán khi OP nói 'Khi tôi tạo Object cho Child Class của Parent Class Constructor chạy', anh ta nói constructor mặc định không làm những gì mình muốn. – user25409

10

Java thực sự có một số quy tắc khá rõ ràng về vấn đề này. Về cơ bản, mã "int i = 45" trong lớp con là một phần ngầm của hàm tạo lớp con và hàm tạo lớp cha luôn luôn chạy trước tiên.

Trình tự các sự kiện là:

  • Tạo đối tượng và không ra tất cả các biến ví dụ.
  • Gọi trình khởi tạo siêu lớp.
  • Gọi hàm tạo siêu lớp.
  • Gọi trình khởi tạo lớp con (int i = 45; trong ví dụ này)
  • Gọi hàm tạo lớp con.

Điều này thực sự khó chịu khi bạn có trường cuối cùng. Bạn có thể khai báo "i" final trong ví dụ của bạn và nhận được kết quả tương tự!

Nói chung, việc gọi các phương thức không riêng tư (hoặc ít nhất là không cuối cùng) trong một hàm tạo là yêu cầu sự cố và thường là nguồn gốc của các lỗi khó chịu. Gọi phương thức trừu tượng là thực sự là ý tưởng xấu (phần lớn thời gian).

+2

Bạn đã bỏ lỡ một bước ẩn. Trong trường hợp các lớp bên trong, tham chiếu ẩn đối với lớp chứa sẽ được gán trước khi hàm tạo của lớp bậc trên được gọi. Ngoài ra, initializers superclass là một phần của constructor superclass, và thực sự nên được liệt kê sau đó. – Antimony

3

Java Beginner: Tôi đã nhận vấn đề của bạn .. 1. Khi bạn tạo đối tượng của lớp trẻ ở đó phương pháp thời gian in() được gọi là duy nhất trong lớp trẻ không ở tầng lớp phụ huynh mặc dù constructor lớp cha gọi đầu tiên bcoz đối tượng là lớp con Vui lòng tham khảo ví dụ sau.

public class Test 
    { 
     public static void main(String[] args) 
     { 
      //create the object of child class 
      Child child = new Child(); 
     } 
    } 

    class Parent 
    { 
     void print() 
     { 
      System.out.println("parent>> i ValueOne="); 
     } 

     Parent() 
     { 
      System.out.println("parent>> i ValueTwo="); 
      print(); 
     } 
    }  

    class Child extends Parent 
    { 
     int i = 45; 


     void print() 
     { 
      System.out.println("Child>>i Value = "+i); 
     } 
    } 

đầu ra:

parent>> i ValueTwo= 
Child>>i Value = 0 

2.Nếu bạn tạo đối tượng lớp cha mẹ tại thời điểm đó phương pháp in() trong lớp cha được gọi. Vui lòng tham khảo ví dụ sau.

public class Test 
    { 
     public static void main(String[] args) 
     { 
      //create the object of Parent class 
      Parent parent = new Parent(); 
     } 
    } 

    class Parent 
    { 
     void print() 
     { 
      System.out.println("parent>> i ValueOne="); 
     } 

     Parent() 
     { 
      System.out.println("parent>> i ValueTwo="); 
      print(); 
     } 
    }  

    class Child extends Parent 
    { 
     int i = 45; 


     void print() 
     { 
      System.out.println("Child>>i Value = "+i); 
     } 
    } 

đầu ra:

parent>> i ValueTwo= 
parent>> i ValueOne= 

3.And tôi nghĩ rằng bạn đã xóa lý do tại sao mà giá trị của i là 0 hoặc 45.

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