2009-02-08 95 views
50

Tôi có một câu hỏi về các hàm tạo mặc định và kế thừa trong Java. Nói chung, nếu bạn viết một lớp và không bao gồm bất kỳ hàm tạo nào, Java cung cấp tự động cho bạn một hàm tạo mặc định (không có tham số), khởi tạo tất cả các biến cá thể của lớp (nếu có) với một số giá trị mặc định (0, null hoặc false). Nếu bạn viết một hàm tạo, tuy nhiên, với một số tham số, và bạn không viết bất kỳ hàm tạo mặc định nào, thì Java không cung cấp một hàm tạo mặc định. Câu hỏi của tôi là: trường hợp với các lớp, kế thừa từ các lớp khác - nếu tôi viết một hàm tạo với một số tham số trong chúng, nhưng không bao gồm một hàm tạo mặc định, chúng có kế thừa hàm tạo mặc định của lớp siêu không?Các hàm tạo và thừa kế mặc định trong Java

+1

Bài đăng có cần một sửa đổi cho dòng mà giả định "Constructor khởi tạo tất cả các biến cá thể của lớp (nếu có) với một số giá trị mặc định (0, null hoặc false)." gây hiểu nhầm cho người đọc? –

Trả lời

51

Các nhà xây dựng không được kế thừa.

Ngoài ra, việc khởi tạo trường được thực hiện bởi máy ảo chứ không phải hàm tạo mặc định. Hàm khởi tạo mặc định chỉ gọi hàm dựng mặc định của lớp cha và hàm tạo mặc định của đối tượng là rỗng. Điểm tốt của thiết kế này là không có cách nào để truy cập các trường chưa được khởi tạo.

+1

Vâng, tôi vừa mới hiểu điều này, potyl bên dưới đã chỉ ra điều này. Nhưng làm thế nào (và khi nào) là các trường được khởi tạo sau đó? (xin vui lòng, xem bình luận của tôi về câu trả lời của potyl). – user42155

+0

Có phải trường hợp khi tôi tạo đối tượng, khi đó Java sẽ tự động đưa ra các giá trị mặc định? Nhưng sau đó một lần nữa, chúng tôi tạo ra các đối tượng với các nhà xây dựng, phải không? – user42155

+0

Có, phải mất một thời gian để thực hiện nghiên cứu w.r.t. khởi tạo. – starblue

10

Trừ khi bạn sử dụng siêu (...) một hàm tạo gọi hàm khởi tạo trống của cha mẹ của nó. Lưu ý: Nó thực hiện điều này trên tất cả các lớp của bạn, ngay cả những lớp mở rộng Object.

Đây không phải là kế thừa, các lớp con không nhận được cùng một hàm tạo với cùng các đối số. Tuy nhiên, bạn có thể thêm các hàm tạo gọi một trong các hàm tạo của lớp siêu.

+0

Với "hàm tạo rỗng", bạn có nghĩa là hàm tạo mặc định, phải không? – user42155

+0

Và nếu bố mẹ không có hàm tạo mặc định thì sao? – user42155

+0

Ở đây tôi có nghĩa là một hàm tạo không có đối số. Thông thường constructor mặc định là một hàm không được định nghĩa. Bạn có thể định nghĩa một hàm tạo không có đối số. –

3

Nếu bạn cung cấp một hàm tạo thì Java sẽ không tạo cho bạn một hàm tạo rỗng mặc định. Vì vậy, lớp dẫn xuất của bạn sẽ chỉ có thể gọi hàm tạo của bạn.

Trình tạo mặc định không khởi tạo biến riêng tư của bạn thành giá trị mặc định. Bằng chứng là có thể viết một lớp không có hàm tạo mặc định và các thành viên riêng của nó được khởi tạo thành các giá trị mặc định. Dưới đây là một ví dụ:

public class Test { 

    public String s; 
    public int i; 

    public Test(String s, int i) { 
     this.s = s; 
     this.i = i; 
    } 

    public Test(boolean b) { 
     // Empty on purpose! 
    } 

    public String toString() { 
     return "Test (s = " + this.s + ", i = " + this.i + ")"; 
    } 

    public static void main (String [] args) { 
     Test test_empty = new Test(true); 
     Test test_full = new Test("string", 42); 
     System.out.println("Test empty:" + test_empty); 
     System.out.println("Test full:" + test_full); 
    } 
} 
+0

Thật thú vị! Tôi đã sống khá lâu với giả định rằng nếu bạn không khởi tạo các biến cá thể trong một hàm tạo, thì Java thực hiện điều này trong hàm tạo mặc định. Vì vậy, trong trường hợp này, các biến được khởi tạo như thế nào? – user42155

+0

Ở đây tôi đã tìm thấy một bài viết hay về khởi tạo trong Java, trả lời câu hỏi của tôi: http://www.javaworld.com/javaworld/jw-03-1998/jw-03-initialization.html?page=1 – user42155

+0

Tạo một đối tượng Ví dụ yêu cầu toán tử "new" cấp phát bộ nhớ và gọi một hàm tạo (được sử dụng cho logic ban đầu). Các nhà thầu của chúng tôi chỉ quan tâm đến các nhà thầu. Tôi đoán rằng phần đầu tiên sẽ chăm sóc khởi tạo mặc định của các thành viên dữ liệu trong khi cấp phát bộ nhớ. – potyl

59
  1. Nếu bạn không thực hiện một constructor, the default empty constructor is automatically created.

  2. Nếu bất kỳ nhà xây dựng nào không gọi rõ ràng một siêu hoặc nhà xây dựng này làm tuyên bố đầu tiên, a call to super() is automatically added.

Luôn luôn.

+2

Liên kết bị hỏng (cảm ơn, Oracle), dưới đây là các liên kết mới: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 và http : //docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.7 – Stoffe

+1

@Stoffe: Tôi đã đề xuất chỉnh sửa sửa liên kết nhờ nhận xét của bạn. Bạn có thể đạt được danh tiếng bằng cách đề xuất chỉnh sửa, vậy tại sao không làm điều đó trong tương lai? – Flimm

+0

Tôi muốn thêm rằng, trong trường hợp 2, lệnh gọi đến siêu không có tham số. – LuxDie

1

Khi chúng ta không tạo một hàm tạo, Java sẽ tạo một hàm tạo mặc định một cách tự động. Nhưng khi chúng ta tạo một hoặc nhiều hàm tạo tùy chỉnh với các đối số, Java không tạo ra bất kỳ hàm tạo mặc định nào. Nếu chúng ta tạo một hoặc nhiều hàm tạo và chúng ta muốn tạo một đối tượng không có bất kỳ đối số hàm tạo nào, chúng ta phải khai báo một hàm tạo rỗng.

+0

"... tạo một đối tượng không có bất kỳ hàm tạo nào Chúng ta phải khai báo ..." => "... tạo một đối tượng không có bất kỳ hàm tạo ** nào, chúng ta phải khai báo ..." –

2

Quy tắc ngón tay cái là Lớp phụ nên gọi bất kỳ hàm tạo nào từ lớp cơ sở. vì vậy nếu bạn không có const mặc định, hãy gọi hàm hiện có từ lớp con.khác khôn ngoan thực hiện const trống trong lớp cơ sở để tránh các vấn đề biên soạn

6

Nguyên tắc cơ bản là một cuộc gọi (hoặc gọi) cho một nhà xây dựng nên là tuyên bố đầu tiên mà JVM cần phải thực hiện,

Vì vậy, khi bạn có một lớp siêu với chỉ constructor parameterized và không có constructor mặc định, và lớp cơ sở không có lời gọi rõ ràng đến constructor parameterized của lớp siêu, JVM cung cấp super(); cuộc gọi ném lỗi vì không có hàm tạo mặc định cho lớp siêu, do đó, hoặc là chúng ta cung cấp một hàm tạo mặc định trong lớp siêu hoặc chúng ta gọi một cách rõ ràng hàm tạo của lớp siêu trong hàm tạo lớp cơ sở. khi chúng ta đưa ra lời gọi rõ ràng, thì JVM không bận tâm đặt dòng super(); như lời gọi hàm tạo nên là câu lệnh đầu tiên của phương thức, điều này không thể xảy ra (vì cuộc gọi rõ ràng của chúng ta).

+0

tôi đoán nó nên hãy thực hành tốt để luôn đặt hàm tạo mặc định ở đó, nếu bạn muốn "xây dựng quá tải" hàm tạo. – lwpro2

5

Mục 8.8.9 của ngôn ngữ Java Specification giải thích chi tiết những gì đang xảy ra:

Nếu một lớp không chứa khai báo constructor, sau đó một constructor mặc định được ngầm tuyên bố. Hình thức của các nhà xây dựng mặc định cho một lớp học đầu cấp, lớp thành viên, hoặc lớp địa phương như sau:

  • các constructor mặc định có khả năng tiếp cận tương tự như các lớp (§6.6). Nhà xây dựng mặc định không có thông số chính thức, ngoại trừ trong một lớp không phải là tư nhân thành viên bên trong, nơi hàm tạo mặc định khai báo rõ ràng một tham số chính thức đại diện cho thể hiện kèm theo ngay lập tức của lớp (§8.8.1, §15.9. 2, §15.9.3).
  • Hàm tạo mặc định không có mệnh đề ném.
  • Nếu lớp được khai báo là đối tượng lớp nguyên thủy, thì hàm tạo mặc định có phần thân trống. Nếu không, hàm tạo mặc định chỉ đơn giản là gọi hàm tạo của lớp bậc trên không có đối số.

Bạn có thể thấy rằng không có sự thừa kế nào xảy ra ở đây: tất cả đều có "ma thuật trình biên dịch" với hàm tạo mặc định được khai báo ngầm định. Đặc tả này cũng làm rõ rằng hàm khởi tạo mặc định chỉ được thêm khi lớp không có hàm tạo nào, nghĩa là câu trả lời cho câu hỏi của bạn là "không": khi bạn cung cấp cho lớp một hàm tạo, truy cập vào hàm tạo mặc định của nó siêu lớp bị mất.

+0

liên kết được tham chiếu: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9 – cellepo

2

Câu trả lời cho câu hỏi của bạn rất đơn giản. Ngụ ý (ẩn), câu lệnh đầu tiên trong bất kỳ hàm tạo nào là 'super();' tức là lệnh gọi hàm tạo không có tham số của lớp siêu, cho đến khi bạn thay đổi nó thành cái gì đó như 'this();', 'this (int)', 'this (String)', 'super (int)', 'super (String) 'v.v. ' this(); ' là hàm tạo của lớp hiện tại.

0

Sẽ có lỗi biên dịch thời gian ... vì Trình biên dịch tìm kiếm Constructor mặc định là Siêu lớp và nếu nó không có ... lỗi của nó ... và chương trình sẽ không biên dịch ...

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