Why it is good practice to declare loggers private, static, and final?

简介: // Jakarta Commons Loggingprivate static final Log log = LogFactory.getLog(MyClass.class);The above code also shows another good practice, which is to...

// Jakarta Commons Logging
private static final Log log = LogFactory.getLog(MyClass.class);
The above code also shows another good practice, which is to pass the Class object to the getLog() method, instead of a string.
Why the java.util.logging.Logger class doesn't even provide a method accepting a Class object is simply beyond me.
Why did the people who developed the java.util.logging package base their API on Log4j yet omit some of the most useful parts of it?
Oh well.Now to the point.
Why it is good practice to declare loggers private, static, and final?
A logger is an internal implementation detail, so it should be private.
You only need one logger for all instances of a class, hence static.
And a logger should not be able to be replaced, thus final.
So if this is good, what's not so good (at least in my opinion)?
Simple - any logger that is not private, static, final, and which doesn't pass in a Class object to getLog()!
For example, consider this common bit of code, declared in some base class:

// Not so good logger declaration
protected final Log log = LogFactory.getLog(getClass());
Why is this bad? Well, it isn't static for one thing.
For another, it uses getClass() to obtain the log.
At first this seems efficient since now all subclasses automatically inherit a ready-made log of the correct runtime type.
So what's the issue here?
The biggest problem with loggers declared in this manner is that you now get all the logging from the superclass mixed in with the logging from the subclass,
and it is impossible in the log output to discern which messages came from which class unless you look at the source.
This is really annoying if the superclass has a lot of logging that you don't want to see, since you cannot filter it out.
Another problem is that your ability to set log levels differently goes away,
for example if a subclass resides in a different package than the superclass.
In that case, if you try to filter out logging from the superclass, you can't because the actual runtime class was used to obtain the logger.
Last, having a protected logger just seems to violate basic object-oriented principles.
Why in the world should subclasses know about an internal implementation detail from a superclass that is a cross-cutting concern, no less?
Anyway, though this is a silly little rant it really is annoying when you extend a superclass that declares a protected logger like this.


Class<? extends ValueOfNull> java.lang.Object.getClass()

Returns the runtime class of this Object.
The returned Class object is the object that is locked by static synchronized methods of the represented class.
The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.
For example, no cast is required in this code fragment:

Number n = 0;
Class<? extends Number> c = n.getClass();

The Class object that represents the runtime class of this object.

相关文章
|
存储 Java 编译器
【Java异常】Variable used in lambda expression should be final or effectively final
【Java异常】Variable used in lambda expression should be final or effectively final
260 0
【Java异常】Variable used in lambda expression should be final or effectively final
|
6月前
|
安全 程序员 编译器
static_cast与dynamic_cast到底是什么?
该文讨论C++中`static_cast`和`dynamic_cast`在处理子类与父类指针转换的情况。总结如下: 1. `static_cast`父类转子类:可能不安全,但不会报错。 2. `static_cast`子类转父类:安全,无错误。 3. `dynamic_cast`父类转子类:若父类有虚函数,运行时检查,成功返回子类指针,失败则为`nullptr`。 4. `dynamic_cast`子类转父类:安全,无错误。
VS2005 error C2864 only static const integral data members can be initialized within a class
VS2005 error C2864 only static const integral data members can be initialized within a class
|
C语言 C++
2023-2-19-什么是static_cast
2023-2-19-什么是static_cast
113 0
Dart报The return type ‘bool‘ isn‘t a ‘void‘, as required by the closure‘s context
Dart报The return type ‘bool‘ isn‘t a ‘void‘, as required by the closure‘s context
|
关系型数据库 MySQL C++
Error:E0415 no suitable constructor exists to convert from “int“ to “Rational“
Error:E0415 no suitable constructor exists to convert from “int“ to “Rational“
187 0
|
Java 程序员 编译器
Variable used in lambda expression should be final or effectively final
Variable used in lambda expression should be final or effectively final
Variable used in lambda expression should be final or effectively final
|
Android开发 Kotlin
【错误记录】Kotlin 编译报错 ( Class ‘Xxx‘ is not abstract and does not implement abstract member )
【错误记录】Kotlin 编译报错 ( Class ‘Xxx‘ is not abstract and does not implement abstract member )
780 0
【错误记录】Kotlin 编译报错 ( Class ‘Xxx‘ is not abstract and does not implement abstract member )