2012-11-08 31 views
12

Tôi có một lớp tiện ích có các phương thức không tĩnh không có biến mẫu. Vì vậy, tôi đang nghĩ đến việc chuyển đổi tất cả các phương thức thành phương thức static. Tôi nghi ngờ sẽ có bất kỳ tác động bộ nhớ hoặc hiệu suất. Nhưng tôi chỉ muốn xác nhận.hiệu suất của phương pháp tĩnh và không tĩnh cho một lớp tiện ích

Việc thay đổi phương thức này thành static có ảnh hưởng đến hiệu suất của chương trình không?

Trả lời

17

Một điều cuối cùng để thêm vào những gì mọi người đã nói ở đây.

Sử dụng phương thức static có chi phí thấp hơn một chút do thực tế bạn đã đảm bảo ràng buộc thời gian biên dịch. Các cuộc gọi phương thức tĩnh sẽ tạo hướng dẫn bytecode invokestatic. ]

Trong trường hợp điển hình, các phương pháp mẫu được ràng buộc trong thời gian chạy và sẽ tạo hướng dẫn bytecode invokevirtual có chi phí cao hơn invokestatic.

Tuy nhiên, điều này chỉ trở nên có liên quan trong trường hợp có khả năng là hàng triệu lần lặp lại và tôi sẽ thận trọng khi điều này thúc đẩy thiết kế lớp học của bạn. Làm những gì có ý nghĩa từ quan điểm thiết kế. Dựa trên mô tả của bạn, các phương pháp static có thể là cách để đi. Thực tế, đây là cách thực hành tương đối chuẩn để tạo lớp tiện ích:

public class MyUtilities { 
    private MyUtilities() { } // don't let anyone construct it. 
    public static String foo(String s) { ... } 
} 
+1

Câu chuyện phức tạp hơn một chút vì 'invokevirtual' không phải là một chỉ dẫn máy thực tế. Trong trường hợp xấu nhất nó sẽ được thực hiện như là một trang web gọi đơn sắc, nhưng nếu lớp là cuối cùng (hoặc hiệu quả cuối cùng bởi đức hạnh của nhà xây dựng tư nhân), nó sẽ là một cuộc gọi hardwired. Ngay cả khi không có điều đó, thời gian chạy có thể nhận thấy rằng không có lớp con và hardwire cuộc gọi nào. –

+0

Vâng, tôi hiểu nó không đảm bảo rằng nó không phải là hardwired, nhưng tôi đã cố gắng để giữ cho lời giải thích đơn giản, như hầu hết mọi người không hiểu nội bộ của jvm. – Matt

+1

Tôi phải nói từ ngữ của bạn là gây hiểu nhầm. Không có "kịch bản điển hình" ở đây: lời gọi phương thức cá thể ** luôn luôn ** biên dịch thành 'invokevirtual'; tương tự như vậy với phương thức tĩnh và 'invokestatic'. –

1

Thông thường đối với các lớp tiện ích không có trạng thái (ví dụ như java.lang.Math) để có phương pháp tĩnh công cộng. Bằng cách này bạn không cần phải tạo một thể hiện của lớp để sử dụng nó.

3

Nếu lớp tiện ích không được phân lớp, các phương thức chuyển đổi không truy cập các biến mẫu tới static là một ý tưởng hay. Bạn nên đi qua các mã và chuyển đổi lời gọi đến cú pháp tĩnh, ví dụ:

int res = utilityInstance.someMethod(arg1, arg2); 

nên được chuyển đổi sang

int res = UtilityClass.someMethod(arg1, arg2); 

cho rõ ràng.

Sẽ không có tác động hiệu suất đáng chú ý: mặc dù các lời gọi tĩnh về mặt lý thuyết hơi kém tốn kém, sự khác biệt quá nhỏ để xem xét quan trọng trong hầu hết các trường hợp.

-1

Sự khác biệt là bạn cần một ví dụ để sử dụng chúng, vì vậy người dùng có để làm cho một ví dụ mà sẽ là một

3

Có hai yêu cầu phải được đáp ứng cho một phương pháp để đủ điều kiện để chuyển đổi vào static:

  1. không có biến mẫu nào được truy cập (trường hợp này được đáp ứng trong trường hợp của bạn);
  2. sẽ không bao giờ cần phải ghi đè (vì điều này bạn có thể phải suy nghĩ).

Tuy nhiên, khi các yêu cầu này được đáp ứng, nó thực sự là khuyến để làm cho phương pháp tĩnh bởi vì nó thu hẹp bối cảnh phương pháp này là chạy bên trong.

Cuối cùng, lưu ý rằng có không có vấn đề hiệu suất để nói về điều này và bất kỳ sự khác biệt lý thuyết nào là thực tế ủng hộ các phương pháp tĩnh vì chúng không liên quan đến độ phân giải phương pháp động. Tuy nhiên, lời gọi phương thức instance là nhanh chóng trong bất kỳ triển khai JVM có liên quan nào.

Theo như bộ nhớ, câu chuyện là như nhau: sự khác biệt về lý thuyết là có lợi cho phương pháp tĩnh, nhưng không có sự khác biệt thực tế nếu so sánh với lớp tiện ích đơn.

17

CHỈNH SỬA: Giải quyết khía cạnh hiệu suất: nó rẻ hơn không phải tạo ra một thể hiện của một cái gì đó vô nghĩa, nhưng sự khác biệt rất có thể là hoàn toàn không liên quan. Tập trung vào một thiết kế rõ ràng có nhiều khả năng là quan trọng theo thời gian.

Phương thức tiện ích thường là tĩnh và nếu tất cả các phương thức trong lớp là tĩnh, có thể tạo ra lớp final và bao gồm hàm tạo riêng ngăn chặn instantation.Về cơ bản, với các lớp tiện ích không đại diện cho bất kỳ "điều" thực nào, nó không có ý nghĩa hợp lý để xây dựng một cá thể - vì vậy hãy ngăn chặn nó. Mặt khác, điều này làm giảm tính linh hoạt: nếu bất kỳ phương pháp tiện ích nào có chức năng mà bạn có thể muốn thay đổi đa hình (ví dụ cho mục đích thử nghiệm) thì hãy xem chúng như phương pháp mẫu - và cố gắng trích xuất một số lớp có ý nghĩa tên để đại diện cho "điều" có liên quan. (Ví dụ: FooConverter có ý nghĩa để khởi tạo - FooUtil không.)

+4

+1 cho đoạn thứ hai. Nếu các phương thức tĩnh được sử dụng, thì sẽ không thể hoán đổi việc thực thi. –

+0

@MarkoTopolnik: Đã thêm một phần ở đầu câu trả lời. –

0

Ý tưởng tốt về phương pháp tĩnh khi bạn định sử dụng chức năng cụ thể rất thường xuyên.

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