Nó thường là thích hợp để tái sử dụng một đối tượng duy nhất thay vì tạo ra một đối tượng chức năng tương đương mới mỗi khi nó là cần thiết. Tái sử dụng có thể là cả hai nhanh hơn và phong cách hơn. Một đối tượng luôn luôn có thể được tái sử dụng nếu nó là bất biến (Item 15). Như một ví dụ cực đoan của những gì không làm, hãy xem xét tuyên bố này: = new String String ("stringette"); // ĐỪNG LÀM THẾ! Những tuyên bố tạo ra một thể hiện mới String mỗi khi nó được thực thi, và không ai trong số những sáng tạo đó đối tượng là cần thiết. Đối số cho các nhà xây dựng String ("stringette") chính là một ví dụ String, chức năng giống hệt với tất cả các đối tượng được tạo ra bởi các nhà xây dựng. Nếu sử dụng điều này xảy ra trong vòng một hoặc một phương pháp thường được viện dẫn, hàng triệu trường hợp String có thể được tạo ra không cần thiết. Các phiên bản cải tiến đơn giản như sau: String s = "stringette"; Phiên bản này sử dụng một ví dụ chuỗi duy nhất, thay vì tạo ra một mới mỗi khi nó được thực thi. Hơn nữa, nó được đảm bảo rằng các đối tượng sẽ được tái sử dụng bởi bất kỳ mã khác đang chạy trong cùng một máy ảo đó xảy ra để có cùng một chuỗi chữ [JLS, 3.10.5]. Bạn thường có thể tránh việc tạo ra các đối tượng không cần thiết bằng cách sử dụng phương pháp nhà máy tĩnh ( Khoản 1) trong ưu tiên cho nhà thầu về các lớp học bất biến mà cung cấp cho cả hai. Ví dụ, các phương pháp nhà máy tĩnh Boolean.valueOf (String) là hầu như luôn luôn thích hợp hơn để các nhà xây dựng Boolean (String). Các nhà xây dựng tạo ra một đối tượng mới mỗi lần nó được gọi là, trong khi các phương pháp nhà máy tĩnh là không bao giờ cần phải như vậy và sẽ không có trong thực tế. Ngoài việc tái sử dụng các đối tượng không thay đổi, bạn có thể sử dụng lại các đối tượng cũng có thể thay đổi nếu bạn biết họ sẽ không được sửa đổi. Dưới đây là một ví dụ hơi tinh tế hơn, và phổ biến hơn nhiều, những gì không nên làm. Nó liên quan đến các đối tượng ngày có thể thay đổi mà không bao giờ thay đổi một khi giá trị của họ đã được tính toán. Mô hình lớp học này một người và có một phương pháp isBabyBoomer đó cho dù người đó là một "baby boomer", nói cách khác, cho dù người đó được sinh ra giữa năm 1946 và 1964: public class Person { tin cuối cùng ngày sinh; // các lĩnh vực khác, phương pháp, và constructor bỏ qua ! // ĐỪNG LÀM THẾ công isBabyBoomer boolean () { // phân bổ không cần thiết của đối tượng đắt Lịch gmtCal = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); gmtCal.set (1946, Lịch .JANUARY, 1, 0, 0, 0); Ngày boomStart = gmtCal.getTime (); gmtCal.set (1965, Calendar.JANUARY, 1, 0, 0, 0); Ngày boomEnd = gmtCal.getTime (); trở lại birthDate.compareTo (boomStart)> = 0 && birthDate.compareTo (boomEnd) <0; } } Phương pháp isBabyBoomer không cần thiết tạo ra một mới Calendar, TimeZone, và hai trường hợp ngày mỗi khi nó được gọi. Các phiên bản sau tránh không hiệu quả này với một initializer tĩnh: class Person { tin cuối cùng ngày sinh; // khác trường, phương thức, và bỏ qua constructor / ** . * Các điểm bắt đầu và kết thúc của sự bùng nổ em bé * / private static ngày thức BOOM_START; private static thức ngày BOOM_END; tĩnh { Lịch gmtCal = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); gmtCal.set (1946, Calendar.JANUARY, 1, 0, 0, 0); BOOM_START = gmtCal. getTime (); gmtCal.set (1965, Calendar.JANUARY, 1, 0, 0, 0); BOOM_END = gmtCal.getTime (); } isBabyBoomer public boolean () { return birthDate.compareTo (BOOM_START)> = 0 && Ngày sinh .compareTo (BOOM_END) <0; } } Các phiên bản cải tiến của lớp Person tạo Lịch, TimeZone, và ngày trường hợp chỉ có một lần, khi nó được khởi tạo, thay vì tạo ra cho họ mỗi khi isBabyBoomer được gọi. Điều này dẫn đến tăng hiệu suất đáng kể nếu phương pháp này được gọi thường xuyên. Trên máy tính của tôi, phiên bản gốc mất 32.000 ms cho 10 triệu lời gọi, trong khi các phiên bản cải tiến có 130 ms, đó là nhanh hơn khoảng 250 lần. Không chỉ là hiệu suất được cải thiện, nhưng như vậy là rõ ràng. Thay đổi boomStart và boomEnd các biến cục bộ cho các lĩnh vực tĩnh cuối cùng làm cho nó rõ ràng rằng những ngày này đang được coi là hằng số, làm cho mã dễ hiểu hơn. Trong sự quan tâm của tiết lộ đầy đủ, các khoản tiết kiệm từ loại này tối ưu hóa sẽ không luôn luôn ấn tượng này, như Calendar trường đặc biệt đắt tiền để tạo. Nếu các phiên bản cải tiến của lớp Person được khởi tạo nhưng phương pháp isBabyBoomer nó không bao giờ được gọi, các BOOM_START và các lĩnh vực BOOM_END sẽ được khởi tạo không cần thiết. Nó sẽ có thể để loại bỏ các initializations không cần thiết bằng cách lười biếng khởi tạo các lĩnh vực này (Mã 71) lần đầu tiên phương pháp isBabyBoomer được gọi, nhưng nó không được khuyến khích. Như thường là trường hợp với khởi lười biếng, nó sẽ làm phức tạp việc thực hiện và sẽ không thể dẫn đến một sự cải thiện hiệu suất đáng kể xa hơn những gì chúng ta đã đạt được (khoản 55). Trong ví dụ trước trong mục này, rõ ràng là các đối tượng trong câu hỏi có thể được tái sử dụng bởi vì họ đã không thay đổi sau khi khởi tạo. Có những tình huống khác, nơi nó là ít rõ ràng hơn. Hãy xem xét trường hợp của adapter [Gamma95, p. 139], còn được gọi là quan điểm. Một bộ điều hợp là một đối tượng mà các đại biểu cho một đối tượng ủng hộ, cung cấp một giao diện thay thế cho các đối tượng ủng hộ. Bởi vì một bộ chuyển đổi không có nhà nước ngoài mà các đối tượng ủng hộ của mình, không cần để tạo ra nhiều hơn một thể hiện của một bộ chuyển đổi cho một đối tượng nhất định. Ví dụ, phương thức keySet của giao diện đồ trả về một điểm Set của đối tượng Bản đồ, bao gồm tất cả các phím trong bản đồ. Ngây thơ, có vẻ như tất cả các cuộc gọi đến keySet sẽ phải tạo ra một thể hiện Set mới, nhưng mọi cuộc gọi đến keySet trên một bản đồ đối tượng nhất định có thể trả lại dụ Set cùng. Mặc dù Đặt dụ trở lại thường là có thể thay đổi, tất cả các đối tượng trả lại có chức năng giống hệt nhau: khi một trong số các đối tượng thay đổi trở lại, do đó, tất cả những người khác, vì tất cả chúng đang được hỗ trợ bởi các đồ cùng một ví dụ. Trong khi nó là vô hại để tạo ra nhiều trường hợp của các đối tượng xem keySet, nó cũng là không cần thiết. Có một cách mới để tạo các đối tượng không cần thiết trong phiên bản 1.5. Nó được gọi là autoboxing, và nó cho phép các lập trình viên để trộn nguyên thủy và đóng hộp các loại nguyên thủy, boxing và unboxing tự động khi cần thiết. Autoboxing mờ nhưng không xóa sự phân biệt giữa các loại nguyên thủy thô sơ và đóng hộp. Có sự phân biệt ngữ nghĩa tinh tế, và sự khác biệt hiệu suất không quá quỷ quyệt (khoản 49). Hãy xem xét các chương trình sau đây, mà tính toán tổng của tất cả các giá trị int tích cực. Để làm điều này, chương trình có sử dụng số học dài, bởi vì một int là không đủ lớn để chứa tổng của tất cả các giá trị int tích cực: // chương trình hideously chậm! Bạn có thể phát hiện ra các đối tượng sáng tạo? static void main (String [] args) {công lâu sum = 0L; for (dài i = 0; i <Integer.MAX_VALUE; i ++) { sum + = i; } System.out.println (tổng hợp); } Chương trình này nhận được câu trả lời đúng, nhưng nó là chậm hơn nhiều so với nó phải là, do một lỗi đánh máy bằng một ký tự. Tổng biến được khai báo là một Long thay vì một thời gian dài, có nghĩa là các chương trình xây dựng khoảng 231 trường hợp dài không cần thiết (khoảng một cho mỗi lần i dài được thêm vào tổng Long). Thay đổi việc kê khai tổng hợp từ Long để lâu sẽ làm giảm thời gian chạy từ 43 giây đến 6,8 giây trên máy tính của tôi. Bài học là rõ ràng:. Thích nguyên thủy để nguyên thủy đóng hộp, và xem ra cho autoboxing không chủ ý item này không nên hiểu sai để ngụ ý rằng đối tượng sáng tạo là tốn kém và cần phải tránh. Ngược lại, sự sáng tạo và cải tạo các vật thể nhỏ mà nhà thầu làm việc ít rõ ràng là giá rẻ, đặc biệt là về việc triển khai JVM hiện đại. Tạo đối tượng bổ sung để tăng cường sự rõ ràng, đơn giản, hoặc quyền lực của một chương trình nói chung là một điều tốt. Ngược lại, tránh tạo ra đối tượng bằng cách duy trì hồ bơi đối tượng của riêng bạn là một ý tưởng tồi trừ khi các đối tượng trong các hồ bơi là vô cùng nặng. Các ví dụ điển hình của một đối tượng mà không biện minh cho bể bơi đối tượng là một kết nối cơ sở dữ liệu. Chi phí của việc thiết lập các kết nối là đủ cao mà nó làm cho tinh thần để tái sử dụng các đối tượng này. Ngoài ra, giấy phép cơ sở dữ liệu của bạn có thể giới hạn bạn đến một số cố định của các kết nối. Nói chung, tuy nhiên, việc duy trì hồ bơi đối tượng của riêng bạn clutters mã của bạn, làm tăng bộ nhớ, và làm tổn hại đến hiệu suất. Triển khai JVM hiện đại đã tối ưu hóa cao thu gom rác dễ dàng làm tốt hơn bể đối tượng như vậy trên các đối tượng trọng lượng nhẹ. Các điểm đối với mặt hàng này là hàng 39 về sao chép phòng thủ. Mục 5 nói, "Đừng tạo ra một đối tượng mới khi bạn cần sử dụng lại một hiện tại", trong khi mục 39 nói, "Không sử dụng một đối tượng hiện khi bạn cần tạo ra một cái mới." Lưu ý rằng các hình phạt cho việc tái sử dụng một đối tượng khi sao chép thủ được gọi cho là lớn hơn nhiều so với các hình phạt cho không cần thiết tạo ra một đối tượng trùng lặp. Không lập bản phòng thủ khi cần thiết có thể dẫn đến lỗi âm ỉ và lỗ hổng bảo mật; tạo các đối tượng không cần thiết chỉ đơn thuần ảnh hưởng đến phong cách và hiệu suất.
đang được dịch, vui lòng đợi..