2009-10-18 33 views
11

sự khác biệt giữa làm điều này là gì:Sự khác biệt giữa instantiating trong trường và instantiating trong constructor là gì?

public class SomeClass { 
    SomeObject obj = new SomeObject(); 
    //rest of the code 
} 

và điều này

public class SomeClass { 
    SomeObject obj; 
    public SomeClass(){ 
     obj = new SomeObject(); 
    } 
    //rest of the code 
} 
+0

bản sao của http://stackoverflow.com/questions/1568722/on-the-thread-safety-of-instance-variable-initialization –

Trả lời

15

Theo chương 12.5 Creation of New Class Instances của ngôn ngữ Java Specification:

Ngay trước khi một tham chiếu đến đối tượng mới tạo được trả về như kết quả, các nhà xây dựng chỉ là xử lý để khởi tạo đối tượng mới sử dụng quy trình sau:

  1. Gán các đối số cho hàm tạo thành tham số mới được tạo biến cho đối tượng này tructor yêu cầu.
  2. Nếu constructor này bắt đầu bằng một lời gọi constructor rõ ràng của khác constructor trong cùng một lớp (sử dụng này), sau đó đánh giá luận và quá trình xây dựng gọi đệ quy sử dụng các cùng năm bước. Nếu người xây dựng đó yêu cầu hoàn tất đột ngột, thì quy trình này hoàn tất đột ngột cho cùng một lý do; nếu không, hãy tiếp tục với bước 5.
  3. Hàm khởi tạo này không bắt đầu bằng hàm tạo rõ ràng gọi hàm tạo khác trong cùng một lớp (sử dụng). Nếu hàm tạo này dành cho một lớp khác không phải là Đối tượng, thì hàm khởi tạo này sẽ bắt đầu bằng cách yêu cầu rõ ràng hoặc ngụ ý yêu cầu của hàm tạo siêu lớp (sử dụng siêu). Đánh giá đối số và xử lý siêu lớp gọi hàm tạo đệ quy bằng cách sử dụng năm bước giống nhau này. Nếu yêu cầu hàm khởi tạo này hoàn thành đột ngột, thì thủ tục này hoàn tất đột ngột vì cùng một lý do .Nếu không, tiếp tục với bước
  4. Execute initializers dụ và ví dụ initializers biến cho lớp này, gán các giá trị của initializers biến dụ cho biến dụ tương ứng, trong trái sang phải thứ tự mà chúng xuất hiện văn bản trong mã nguồn cho lớp học. Nếu việc thực hiện bất kỳ các trình khởi tạo này dẫn đến một ngoại lệ , thì không thêm trình khởi chạy nào được xử lý nữa và thủ tục này hoàn tất đột ngột với trường hợp ngoại lệ đó. Nếu không, tiếp tục với bước 5. (Trong một số đầu triển khai, trình biên dịch sai bỏ qua các mã để khởi tạo một lĩnh vực nếu biểu thức khởi tạo lĩnh vực là một biểu thức hằng số có giá trị tương đương với giá trị khởi tạo mặc định cho loại của nó.)
  5. Thi hành phần còn lại của phần thân của hàm tạo này. Nếu việc thực thi đó hoàn thành đột ngột, thì quy trình này hoàn tất đột ngột vì lý do tương tự. Nếu không, thủ tục này hoàn tất bình thường.

Vì vậy, sự khác biệt chỉ là bước (bước 4. hoặc bước 5.) nhưng kết quả là như nhau.

-3

Thời gian xây dựng. Việc đầu tiên được thực hiện trước khi nhập chính. Việc xây dựng đối tượng khác bị trì hoãn cho đến khi ctor của SomeClass được gọi.

+5

thế nào là người đầu tiên sẽ được thực hiện trước khi chính? Nó không phải là tĩnh ... – Zed

+0

xấu của tôi ... :(Ví dụ đầu tiên sẽ tạo SomeObject ngay trước khi constructor được chạy ... Đúng? – dicroce

+0

Câu trả lời giống như @Pascal được sao chép từ JLS xem # 4 và # 5 –

0

Trong trường hợp đầu tiên, obj sẽ được khởi chạy trước khi hàm khởi tạo được chạy. Đây là một sắc thái quan trọng khi bạn có các lớp con. Trật tự của nhà thầu và khối khởi tạo sẽ là:

  1. lớp cha initializers
  2. constructor lớp cha
  3. initializers lớp con
  4. lớp con constructor
+1

Đó không phải là cách giải thích của tôi đối với §12.5 của JLS và tôi không nghĩ đó là sự thật –

+0

Đó là sai.Javac tạo mã trong constructor * sau * một lời gọi tới super constructor Tôi hiểu C# khác (nhưng bạn không thể sử dụng 'this' trong các biểu thức như vậy). –

2

Sự khác biệt duy nhất là trong lúc which step tài liệu tham khảo được khởi tạo . Hiệu ứng cuối cùng là như nhau.

1

Đây chỉ là vấn đề về phong cách, nó biên dịch thành cùng một mã.

Cá nhân tôi có xu hướng đặt tất cả khởi tạo các phiên bản trong các hàm tạo, vì nó hoạt động thống nhất cho tất cả các trường hợp.

0

Một khía cạnh chưa được đề cập:

public class SomeClass { 
    SomeObject obj = new SomeObject(); 
    //rest of the code 
} 

sẽ khởi tạo obj đến một giá trị cố định. Nhưng khi khởi tạo trong một hàm tạo, bạn có thể có khởi tạo phụ thuộc vào các tham số của hàm tạo hoặc (với nhiều hàm tạo) sử dụng các biểu thức khởi tạo hoàn toàn khác nhau, ví dụ:

public class SomeClass { 
    private SomeObject obj; 
    public SomeClass(int length){ 
     obj = new SomeObject(3 * length + 7); 
    } 
    //rest of the code 
} 
Các vấn đề liên quan