2011-07-11 33 views

Trả lời

160
  • private - vì vậy mà không có lớp học khác có thể cướp logger của bạn
  • static - vì vậy chỉ có một logger dụ mỗi lớp, cũng tránh những nỗ lực để serialize logger
  • final - không cần phải thay đổi logger trong suốt thời gian của lớp học

Ngoài ra, tôi thích tên log đơn giản nhất có thể, nhưng mang tính mô tả.

EDIT: Tuy nhiên có một ngoại lệ thú vị để các quy tắc:

protected final Logger log = LoggerFactory.getLogger(getClass()); 

như trái ngược với:

private static final Logger log = LoggerFactory.getLogger(Foo.class); 

Cách cựu cho phép bạn sử dụng tên logger cùng (tên của thực tế lớp) trong tất cả các lớp trong toàn bộ hệ thống phân cấp thừa kế. Vì vậy, nếu Bar kéo dài Foo, cả hai sẽ đăng nhập vào Bar trình ghi nhật ký. Một số tìm thấy nó trực quan hơn.

+0

+1, Trả lời nằm trong các công cụ sửa đổi. – mre

+24

nếu tĩnh và cuối cùng thay vì LOG (chữ hoa) – zacheusz

+29

* @ zacheusz *, tôi biết, đó là vấn đề. Một số theo quy ước đặt tên Java theo tôn giáo (không có gì sai với điều đó), nhưng tôi thích viết dễ dàng hơn và dễ chịu hơn để đọc tên 'log' hơn là phân tán mã bằng' LOG'. Chỉ là vấn đề của dev. thỏa thuận nhóm. –

2

Khi nào bạn muốn thay đổi giá trị của trường?

Nếu bạn không bao giờ thay đổi giá trị, làm cho trường cuối cùng làm cho nó rõ ràng mà bạn sẽ không bao giờ thay đổi giá trị.

+1

Trong nhiều trường hợp, hiển nhiên là không thêm từ cuối cùng, trường hợp này trở thành một loại rác. – Dima

+0

@Dima: Tôi vẫn biết ơn rằng trình biên dịch sẽ vẫn ném một lỗi nếu tôi * làm * vô tình cố gắng thay đổi giá trị trong những trường hợp này ... –

2

Bởi vì đó thường là loại chức năng có thể được chia sẻ trên tất cả các trường hợp đối tượng của bạn. Nó không có ý nghĩa nhiều (90% thời gian) để có một logger khác nhau cho hai trường hợp của cùng một lớp.

Tuy nhiên, bạn cũng có thể thấy đôi khi các lớp logger được khai báo là đơn hoặc thậm chí chỉ cung cấp các hàm tĩnh để ghi lại nội dung của bạn.

1

Thông thường bạn khởi tạo trình ghi nhật ký để sử dụng tên lớp - nghĩa là nếu chúng không tĩnh, bạn sẽ kết thúc với mỗi cá thể của lớp có thể hiện của nó (dấu chân bộ nhớ cao), nhưng tất cả các logger này sẽ chia sẻ cùng một cấu hình và hoạt động giống hệt nhau. Đó là lý do đằng sau bit static. Ngoài ra, vì mỗi Logger được khởi tạo với tên lớp, để ngăn xung đột với các lớp con, bạn khai báo nó là private để nó không thể được kế thừa. final xuất phát từ điểm mà bạn thường không thay đổi Logger trong khi thực hiện - vì vậy khi đã khởi tạo, bạn không bao giờ "định cấu hình lại" - trong trường hợp đó là hợp lý để đảm bảo nó cuối cùng đảm bảo không ai có thể thay đổi nó (do nhầm lẫn hoặc cách khác). Tất nhiên, nếu bạn định sử dụng Logger theo cách khác, bạn có thể cần NOT để sử dụng static final - nhưng tôi dự đoán 80% ứng dụng sẽ sử dụng ghi nhật ký như đã giải thích ở trên.

4

static có nghĩa là bạn chỉ tạo ra một Logger mỗi lớp, không phải là một logger mỗi dụ của lớp học của bạn. Nói chung, đây là những gì bạn muốn - như logger có xu hướng thay đổi chỉ dựa trên lớp.

final có nghĩa là bạn sẽ không thay đổi giá trị của biến số logger. Đó là sự thật, vì bạn hầu như luôn luôn ném tất cả các thông điệp tường trình (từ một lớp) vào cùng một bộ ghi. Ngay cả trong những trường hợp hiếm hoi mà một lớp có thể muốn gửi một số thông điệp đến một trình ghi nhật ký khác, nó sẽ rõ ràng hơn để tạo một biến nhật ký khác (ví dụ: widgetDetailLogger) thay vì bằng cách thay đổi giá trị của biến tĩnh khi đang di chuyển.

0

Trong hầu hết các trường hợp, bạn sẽ thay đổi giá trị và công cụ sửa đổi final đánh dấu nó. Bạn không cần các cá thể riêng biệt cho từng cá thể lớp - vì vậy, static. Và đầu tiên của tất cả điều này là cho hiệu suất - nó có thể được tối ưu hóa độc đáo (cuối cùng) và lưu memmory (tĩnh).

3

Để trả lời câu hỏi đó, bạn nên tự hỏi "tĩnh" và "cuối cùng" là gì.

Đối với trình ghi nhật ký, (tôi giả sử bạn nói về lớp LoggerJ Logger) bạn muốn một danh mục cho mỗi lớp. Mà nên dẫn đến thực tế là bạn chỉ định nó một lần, và không cần nhiều hơn một cá thể mỗi lớp. Và có lẽ không có lý do gì để phơi bày đối tượng Logger của lớp này sang lớp khác, vậy tại sao không làm cho nó riêng tư và tuân theo một số nguyên tắc OO.

Ngoài ra, bạn nên lưu ý rằng trình biên dịch có thể tận dụng lợi ích của điều đó. Vì vậy, mã của bạn hoạt động tốt hơn một chút :)

7

Kiểm tra bài đăng trên blog này: Get Rid of Java Static Loggers. Đây là cách bạn sử dụng slf4j với jcabi-log:

import com.jcabi.log.Logger; 
class Foo { 
    void save(File f) { 
    Logger.info(this, "file %s saved successfully", f); 
    } 
} 

Và không bao giờ sử dụng nhiễu tĩnh nữa.

+0

Một giải pháp thay thế thú vị và chắc chắn là sạch hơn. Tôi tự hỏi làm thế nào quy mô này so với logger lớp cá nhân. – Ross

+5

Viết nhật ký dài hơn .. (này, ...) mỗi lần. Nah. –

0

Ngoài những lý do được đưa ra trong câu trả lời khác một điều tôi chạy vào là nếu logger của tôi là không phải tĩnh cũng không chính thức:

... 
public Logger logger = LoggerFactory.getLogger(DataSummary.class); 

public String toJson() { 
    GsonBuilder gsonBuilder = new GsonBuilder(); 
    return gsonBuilder.create().toJsonTree(this).toString(); 
} 
... 

trong những trường hợp nhất định (khi tôi đã sử dụng thư viện Gson) Tôi sẽ nhận được ngoại lệ stackoverflow. Tình hình cụ thể của tôi là khởi tạo lớp chứa trình ghi nhật ký không tĩnh. Sau đó gọi phương thức toJson mà gọi GsonBuilder:

... 
DataSummary ds = new DataSummary(data);  
System.out.println(ds.toJson()); 
... 
1

Mã này là dễ bị tổn thương, nhưng, sau khi Java7, chúng ta có thể sử dụng Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); thay vì logger tĩnh.

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