2010-09-10 30 views
32

Có ai biết tại sao bạn có thể tham chiếu phương thức static trong dòng đầu tiên của hàm tạo bằng cách sử dụng this() hoặc super(), nhưng không phải là phương pháp không tĩnh?Tại sao tôi không thể tham chiếu đến một phương thức thể hiện trong khi gọi một constructor một cách rõ ràng?

Hãy xem xét các hoạt động sau:

public class TestWorking{ 
    private A a = null; 
    public TestWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestWorking(B bParam) 
    { 
     this(TestWorking.getAFromB(bParam)); 
    } 

    //It works because its marked static. 
    private static A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 

Và không làm việc ví dụ sau:

public class TestNotWorking{ 
    private A a = null; 
    public TestNotWorking(A aParam){ 
     this.a = aParam; 
    } 

    public TestNotWorking(B bParam) 
    { 
     this(this.getAFromB(bParam)); 
    } 

    //This does not work. WHY??? 
    private A getAFromB(B param){ 
     A a = new A(); 
     a.setName(param.getName()); 
     return a; 
    } 
} 
+1

Nó có thể chỉ là mã mẫu nhưng một mối quan tâm tôi có về mã này là bạn có logic để xây dựng một thể hiện 'A' từ một thể hiện' B' được chôn trong lớp thứ ba 'TestNotWorking'. –

+0

Tôi đồng ý với mối quan tâm của bạn. Lý do tôi làm như sau: Tôi đang sử dụng API của bên thứ ba có khả năng giới hạn trong lớp và lớp học được đánh dấu cuối cùng.Cách duy nhất là sao chép đối tượng gốc và làm việc trên bản sao. Tôi đã sử dụng đối tượng gốc làm tham số cho đối tượng mới của mình. Vì mục đích của ví dụ, tôi đã sửa đổi nó một chút. – Koekiebox

+0

@Koekiebox Tại sao bạn tự hỏi rằng TestNotWorking.getAFromB (bParam) không hoạt động? nó là phương pháp thể hiện. bạn nên tạo đối tượng hoặc sử dụng nó. – gstackoverflow

Trả lời

16

phương pháp không tĩnh là phương pháp dụ. Đây là chỉ có thể truy cập trong trường hợp hiện có, và ví dụ không tồn tại được nêu ra khi bạn đang ở trong constructor (nó vẫn đang được xây dựng).

Tại sao lại như vậy? Bởi vì các phương thức instance có thể truy cập các instance (non-static), có thể có các giá trị khác nhau trong các instance khác nhau, vì vậy nó không có ý nghĩa khi gọi phương thức này trên một cái gì đó khác với instance đã có.

+28

Điều này là gần, nhưng không chính xác. Các thể hiện * do * tồn tại khi bạn đang ở trong một hàm tạo, và bạn * có thể * gọi các phương thức cá thể trên chúng. Tuy nhiên, bạn không thể làm điều đó cho đến khi nhà xây dựng siêu hạng đã hoàn thành. Nếu bạn muốn gọi chúng trong constructor của riêng bạn, đó là tốt, nhưng lớp siêu phải được hoàn thành. – erickson

+0

Đây không phải là câu trả lời chính xác. Nhận xét cũng không nhận được điểm hoàn toàn bởi vì câu hỏi không phải là về việc gọi hàm dựng siêu nhưng hàm tạo từ cùng một lớp tất nhiên nó cũng là vì chúng ta cần gọi hàm tạo siêu đầu tiên, nhưng câu trả lời và nhận xét không đặt nó rõ ràng. –

+0

Còn mã này thì sao? ** class ClassForTest { ClassForTest (int k) { }; { phương thức(); } ClassForTest() { điều này (1); }; int method() {return 1;} } ** – gstackoverflow

1

Tôi nghĩ rằng đó là vì các biến mẫu cuối cùng chưa được đặt (vì vậy bạn chưa có trường hợp nào) và một phương pháp thể hiện có thể truy cập một. Trong khi tất cả các khởi tạo tĩnh đã được thực hiện trước khi gọi hàm tạo.

Greetz, GHad

1

bởi vì khi bạn gọi này hoặc siêu trong constructor đối tượng của bạn không xây dựng được nêu ra. (trường hợp của bạn chưa được khởi tạo hoàn toàn). vì vậy gọi một phương thức thể hiện không tạo ra cảnh.

0

Nếu phương pháp không tĩnh thì bạn phải gọi nó trên một đối tượng.

Trong ví dụ thứ hai, bạn cần tạo đối tượng lớp TestNotWorking và gọi getAFromB trên đối tượng đó.

Cái gì như:

object = new TestNotWorking(); 
object.getAFromB(bParam); 
1

TestNotWorking không được khởi tạo vào thời điểm đó. Vấn đề là: constructor đầu tiên (TestNotWorking (A aParam)) có thể gọi super() (nội bộ nó luôn luôn), nghĩa là bạn sẽ gọi một method trước khi constructor của superclass được gọi. Đó là bất hợp pháp.

11

Xem Java Language Specification 8.8.7.1. Này khẳng định

Một tuyên bố constructor gọi rõ ràng trong một cơ thể constructor có thể không đề cập đến bất kỳ biến dụ hoặc các phương pháp dụ hoặc các lớp bên trong khai báo trong lớp này hay bất kỳ lớp cha, hoặc sử dụng this hoặc super trong bất kỳ biểu hiện; nếu không, một lỗi biên dịch sẽ xảy ra.

Điều này là do bạn không thể gọi phương thức thể hiện trước khi cá thể được tạo. Bằng cách này, nó có thể gọi một phương pháp dụ sau này trong constructor (mặc dù không phải là một giải pháp cho bạn).

+0

** hoặc sử dụng điều này hoặc siêu trong bất kỳ biểu thức nào; nếu không, một lỗi biên dịch xảy ra ** vui lòng làm rõ – gstackoverflow

+0

@Marc có nghĩa là cá thể được tạo ra trong heap sau khi lời gọi hàm tạo siêu lớp rõ ràng/ngầm định được thực hiện, mặc dù khởi tạo của nó chưa hoàn thành? – dannail

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