Java: Lớp tĩnh?


130

Tôi có một lớp đầy đủ các chức năng tiện ích. Khởi tạo một thể hiện của nó không có ý nghĩa ngữ nghĩa, nhưng tôi vẫn muốn gọi các phương thức của nó. Cách tốt nhất để đối phó với điều này là gì? Lớp tĩnh? Trừu tượng?


14
Bằng cách này, bạn không thể tạo một lớp cấp cao nhất tĩnh ...
Jon

Câu trả lời:


163

Hàm tạo riêng và các phương thức tĩnh trên một lớp được đánh dấu là cuối cùng.


19
@matt b: Như David Robles đã chỉ ra trong câu trả lời của anh ấy, bạn không cần phải làm cho lớp cuối cùng ... nó không thể được phân lớp vì một lớp con sẽ không thể gọi một nhà xây dựng siêu hạng vì nó là riêng tư. Tuy nhiên ... không có hại trong việc rõ ràng. Nhưng jfyi :-).
Tom

93

Theo cuốn sách tuyệt vời "Java hiệu quả" :

Mục 4: Thi hành tính không đáng kể với một nhà xây dựng tư nhân

- Cố gắng thực thi tính không đáng kể bằng cách làm cho một lớp trừu tượng không hoạt động.

- Một hàm tạo mặc định chỉ được tạo nếu một lớp không chứa các hàm tạo rõ ràng, do đó một lớp có thể được tạo thành không đáng kể bằng cách bao gồm một hàm tạo riêng:

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

Bởi vì hàm tạo rõ ràng là riêng tư, nó không thể truy cập được bên ngoài lớp. AssertsError không bắt buộc nghiêm ngặt, nhưng nó cung cấp bảo hiểm trong trường hợp hàm tạo vô tình được gọi từ trong lớp. Nó đảm bảo rằng lớp sẽ không bao giờ được khởi tạo trong bất kỳ trường hợp nào. Thành ngữ này hơi phản trực giác, vì hàm tạo được cung cấp rõ ràng để nó không thể được gọi. Do đó, khôn ngoan là bao gồm một nhận xét, như được hiển thị ở trên.

Là một tác dụng phụ, thành ngữ này cũng ngăn lớp bị phân lớp. Tất cả các hàm tạo phải gọi một hàm tạo của lớp bậc trên, rõ ràng hoặc ẩn và một lớp con sẽ không có hàm tạo của lớp bậc trên có thể truy cập được để gọi.


1
Tại sao bạn lại chọn AssertionErrorqua lựa chọn thay thế khác như IllegalStateException, UnsupportedOperationException, vv?
Pacerier

@Pacerier Xem cái này .
bcsb1001

@ bcsb1001, Điều đó đưa chúng ta đến điều này .
Pacerier

21

Âm thanh như bạn có một lớp tiện ích tương tự như java.lang.Math .
Cách tiếp cận có lớp cuối cùng với hàm tạo riêng và các phương thức tĩnh.

Nhưng hãy cẩn thận với những gì nó làm cho khả năng kiểm tra, tôi khuyên bạn nên đọc bài viết này Phương thức tĩnh là cái chết đối với khả năng kiểm tra


Vì vậy, java.lang.Math là "cái chết cho khả năng kiểm tra"?
Pacerier

1
Thật thú vị khi xem điểm số của nó như thế nào khi chạy qua code.google.com/p/testability-explorer
vương miện

6

Chỉ cần bơi ngược dòng, các thành viên tĩnh và các lớp không tham gia vào OO và do đó là xấu xa. Không, không phải là xấu, nhưng nghiêm túc, tôi muốn giới thiệu một lớp học bình thường với một mẫu đơn để truy cập. Bằng cách này, nếu bạn cần ghi đè hành vi trong mọi trường hợp, đó không phải là một trang bị chính. OO là bạn của bạn :-)

$ 0,02 của tôi


17
Singletons cũng bị coi là ác.
Dan Dyer

3
Bạn sử dụng hàm tạo riêng để ngăn bất kỳ ai khởi tạo hoặc phân lớp lớp. Xem câu trả lời của David Robles: stackoverflow.com/questions/1844355/java-static- class / từ
cướp

5
singleton không ác hơn tiêm phụ thuộc :)
chối cãi

12
OO có vị trí của nó, nhưng có những lúc nó không thực tế hoặc sẽ lãng phí tài nguyên - ví dụ, một thứ đơn giản như Math.abs (). Không có lý do gì để khởi tạo một đối tượng chỉ vì mục đích khởi tạo một đối tượng, khi một cuộc gọi phương thức tĩnh cũng sẽ phục vụ bạn mà không cần bất kỳ chi phí OO nào. ;)
cướp

2
@rob re OO, tôi đồng ý, Math.Abs ​​có lẽ không bao giờ cần một ví dụ. Khi tôi nghe "tôi có một lớp tiện ích", tôi thấy Math.Avg (), nơi bạn cần thêm hỗ trợ cho mức trung bình có trọng số. Tôi thấy một trình tạo Url, param in, url out cần được cấu trúc lại để hỗ trợ href, hoặc chỉ url, v.v. Vì những lý do này, có lớp tiện ích dựa trên OO có thể trả lại. Ngoài ra, bây giờ tôi sẽ bỏ chiến thuật phòng thủ OO tiêu chuẩn, thử nghiệm! / tôi vịt
Bennett Dill

3

nhận xét về các đối số "nhà xây dựng riêng": thôi nào, các nhà phát triển không phải là ngu ngốc; nhưng họ lười biếng tạo một đối tượng sau đó gọi phương thức tĩnh? sẽ không xảy ra.

đừng dành quá nhiều thời gian để đảm bảo rằng lớp học của bạn không thể bị lạm dụng. có một số niềm tin cho các đồng nghiệp của bạn. và luôn có một cách để lạm dụng lớp học của bạn cho dù bạn bảo vệ nó như thế nào. điều duy nhất không thể bị lạm dụng là một thứ hoàn toàn vô dụng.


7
Một người đã xem (trong mã sản xuất, không phải mã sinh viên jsut) object.staticMethod Tôi nghĩ bạn đánh giá quá cao khả năng của Joe Random Lập trình viên! :-P
TofuBeer

2
  • Lớp cuối cùng và nhà xây dựng riêng (tốt nhưng không cần thiết)
  • Phương pháp tĩnh công khai

1

Không có điểm nào trong việc khai báo lớp là static. Chỉ cần khai báo các phương thức của nó staticvà gọi chúng từ tên lớp là bình thường, như lớp Math của Java .

Ngoài ra, mặc dù không nhất thiết phải làm cho nhà xây dựng riêng tư, nhưng đó là một ý tưởng tốt để làm như vậy. Việc đánh dấu riêng của hàm tạo sẽ ngăn người khác tạo các thể hiện của lớp của bạn, sau đó gọi các phương thức tĩnh từ các thể hiện đó. (Các cuộc gọi này hoạt động giống hệt nhau trong Java, chúng chỉ gây hiểu lầm và làm tổn thương tính dễ đọc của mã của bạn.)


1
Ngoài ra, đừng quên tạo một nhà xây dựng tư nhân.
Asaph

@Asaph: Đồng ý. Tôi đã thêm một chút vào đó cho câu trả lời của tôi. Cảm ơn.
Bill the Lizard

Nếu bạn muốn các phương thức tĩnh trong một lớp bên trong, thì lớp đó cũng phải là tĩnh.
Rui Marques

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.