2010-05-18 38 views
38

Tôi có một thức thành viên không tĩnh:Trong Java, một trường cuối cùng có thể được khởi tạo từ một trình trợ giúp hàm tạo không?

private final HashMap<String,String> myMap; 

Tôi muốn khởi tạo nó sử dụng một phương pháp gọi là bởi các nhà xây dựng. Vì myMap là cuối cùng, phương thức "helper" của tôi không thể khởi tạo nó trực tiếp. Tất nhiên tôi có các tùy chọn:

Tôi có thể triển khai mã khởi tạo myMap trực tiếp trong hàm tạo.

MyConstructor (String someThingNecessary) 
{ 
    myMap = new HashMap<String,String>(); 

    myMap.put("blah","blahblah"); 
    // etc... 

    // other initialization stuff unrelated to myMap 
} 

Tôi có thể có phương pháp trợ giúp của tôi xây dựng HashMap, trả về hàm tạo và sau đó gán hàm tạo cho myMap.

MyConstructor (String someThingNecessary) 
{ 
    myMap = InitializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 

private HashMap<String,String> InitializeMyMap(String someThingNecessary) 
{ 
    HashMap<String,String> initializedMap = new HashMap<String,String>(); 

    initializedMap.put("blah","blahblah"); 
    // etc... 

    return initializedMap; 
} 

Phương pháp # 2 là tốt, tuy nhiên, tôi có thể cho phép phương pháp trợ giúp trực tiếp thao tác với myMap. Có lẽ một công cụ sửa đổi cho biết nó chỉ có thể được gọi bởi hàm tạo?

MyConstructor (String someThingNecessary) 
{ 
    InitializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 


// helper doesn't work since it can't modify a final member 
private void InitializeMyMap(String someThingNecessary) 
{ 
    myMap = new HashMap<String,String>(); 

    myMap.put("blah","blahblah"); 
    // etc... 
} 
+0

Bạn có biết người trả lời câu hỏi của bạn sẽ làm gì không? Có, họ sẽ thử nó bằng cách mở Eclipse và sao chép-dán mã của bạn! :) – Simon

+5

@Simon Câu hỏi của tôi là yêu cầu thay thế cho những gì tôi đã thử. Tôi tự hỏi nếu một người có kiến ​​thức tốt hơn về ngôn ngữ đó hơn tôi có thể hướng dẫn tôi đến một từ khóa hoặc mô hình mà tôi không biết. – csj

+3

câu trả lời là Không. Nguồn: Đặc tả ngôn ngữ Java 8.3.1.2 – mihi

Trả lời

12

Phương pháp # 2 là lựa chọn tốt nhất của bạn. Vấn đề là nếu bạn có một nhiệm vụ trong một phương thức riêng thì không có gì ngăn cản các mã khác trong lớp bên ngoài constructor gọi nó, mà sau đó sẽ tạo ra một vấn đề với nhiệm vụ thứ hai đã cố gắng đến trường cuối cùng.

Java không có cấu trúc của một phương thức riêng biệt chỉ có thể được gọi trong khi xây dựng.

Để hoàn chỉnh, chúng tôi có thể làm cho một lựa chọn thứ ba, nơi bạn gán bản đồ lúc khởi tạo và sau đó có phương pháp helper điền nó:

private final HashMap<String, String> myMap = new HashMap<String, String(); 

Và sau đó:

MyConstructor (String someThingNecessary) 
{ 
    initializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 


// helper doesn't work since it can't modify a final member 
private void initializeMyMap(String someThingNecessary) 
{ 

    myMap.clear(); 
    myMap.put("blah","blahblah"); 
    // etc... 
    } 

Và nếu bạn thực sự muốn gây nhầm lẫn bạn có thể sử dụng trình khởi tạo thay vì hàm tạo, nhưng bạn không nên làm điều đó, vì vậy trừ khi bạn thực sự cần biết, tôi sẽ không mở rộng trên đó.

+5

Thực ra, Java có. Nó được gọi là một hàm tạo ;-) – Joey

+1

@Johannes no, anh ta có nghĩa là không có chỉ định sub-constructor nào cho phép gán các biến cuối cùng với điều kiện là phương thức này chỉ có thể được gọi từ hàm tạo. – corsiKa

+0

@Yishai. Cảm ơn bạn đã thay thế. Ngoài ra, liên quan đến initializers, tôi không nghĩ rằng nó sẽ làm việc anyway, kể từ khi nội dung HashMap thực sự phụ thuộc vào các đối số cho các nhà xây dựng. – csj

1

Tùy chọn # 2 là tùy chọn có giá trị nhất, vì bạn có thể chia sẻ nó trong số tất cả các nhà xây dựng. Những gì chúng ta cần ở đây, là bộ khởi tạo bộ sưu tập của C#. :)

(BTW: # 3 sẽ không biên dịch)

+0

Cảm ơn sự giúp đỡ của bạn Simon. Tôi biết từ khi đi mà # 3 sẽ không biên dịch. Tôi đã hy vọng có thể có một cách để làm cho nó hợp pháp bằng cách đảm bảo rằng người trợ giúp sẽ chỉ được gọi từ nhà xây dựng. Có vẻ như điều này là không thể. – csj

13

Làm thế nào về triển khai xây dựng tư nhân mà khởi HashMap của bạn, và sau đó có nhà xây dựng chính của bạn (s) gọi đó là xây dựng tư nhân?

Đối với ví dụ điển

// Helper function to initialize final HashMap. 
private MyConstructor() 
{ 
    myMap = new HashMap<String,String>(); 
    myMap.put("blah","blah"); 
} 

MyConstructor (String someThingNecessary) 
{ 
    // Initialize the HashMap. 
    this(); 
    // Other initialization code can follow. 
} 

Bạn có thể thay đổi chữ ký của các nhà xây dựng helper tin khi cần thiết (ví dụ như để cung cấp dữ liệu tham số hoặc để làm chữ ký khác nhau từ bất kỳ nhà xây dựng công cộng).

+0

Tôi nghĩ rằng giải pháp này là những gì @Joey đã ám chỉ ở trên khi ông nói, "Thực ra, Java có. Nó được gọi là một nhà xây dựng," để đáp lại nhận xét của Yishai rằng "Java không có cấu trúc của một phương pháp riêng biệt mà chỉ có thể được gọi trong xây dựng." – cjerdonek

+0

Tôi thích ý tưởng này. Thật không may, nó ngăn cản tôi đưa ra phương thức một tên hợp lý (như, InitializeMyMap) đại diện cho những gì nó khởi tạo. Cảm ơn bạn đã đăng câu hỏi cũ. Tôi luôn đánh giá cao những ý tưởng mới, hoặc làm rõ những ý tưởng cũ. – csj

+0

Cảm ơn, @csj. Tôi đang tìm kiếm một câu trả lời cho cùng một câu hỏi và nghĩ về điều này. Không có cách tiếp cận nào được đề xuất trước đó sẽ hoạt động rất tốt cho trường hợp sử dụng của tôi đồng thời khởi tạo một số trường cuối cùng. Đối với tên, có, nó có thể được tốt hơn. Nhưng ít nhất nó phù hợp với các nhà thầu khởi tạo một cái gì đó. :) Tôi mới sử dụng Java và sẽ không ngạc nhiên nếu có một giải pháp tốt hơn nữa. – cjerdonek

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