声明变量final和static
此评论是在代码审核中进行的,而制作该评论的人不再在我们的团队中。
在运行时必须由类加载器解析的任何类型都不应该具有被声明为final和static的引用保持的实例。
这是代码行:
private final static Logger log = LoggerFactory.getLogger(MyClass.class);
我熟悉声明loggers静态或非静态的争论,但这个评论似乎更为通用。 我找不到任何关于为什么静态和最终都不好的解释。 有人可以详细说明吗?
评论很可能与Classloader Leaking的问题有关( 这是一篇好文章 )。
简而言之,这个问题发生在需要重新加载类加载器的环境中。 如果通过类加载器动态加载类,然后尝试重新加载类加载器,则使用通过此类加载器创建的类的对象保留静态最终字段将阻止卸载类加载器本身。 一旦发生这种情况,就会出现OutOfMemoryError
。
上面链接的文章列出了可能产生此行为的主要罪魁祸首之间的日志库,以及可以用来解决泄漏的措施(例如显式释放类加载器)。
代码行非常精细,并且没有真正的问题,因为变量是final
和static
。
也许发表评论的人对以下内容感到困惑。
在Java中,当您创建int
类型的public final static
变量时(例如;它也适用于其他一些类型),那么编译器可能会在您使用该变量的地方替换实际常量值而不是引用变量。 例如,假设您有以下内容:
class A { public final static int VALUE = 3; } public class B { public static void main(String[] args) { System.out.println(A.VALUE); } }
当你编译并运行它时,它显然会打印3。
现在假设您更改了A
类并设置了VALUE = 4
。 你会期望如果你重新编译A
类然后运行B
类(不重新编译B
类),你会看到4
。 但是会发生什么,你仍然会看到3
。 这是因为当编译B
类时, B
类中的A.VALUE
被实际常量值3
取代。
这是Java编译器对常量进行的优化。
如您所见,这可能会导致问题,如果您在类的公共API中有这样的常量。 如果更改此类常量的值,则代码的用户必须重新编译其代码。
但是在您在问题中发布的代码中,这不是问题,因为变量是private
。
更多细节:
Java语言规范13.4.9
- 如何防止具有META-INF \ services \ javax.xml.transform.TransformerFactory的xalan.jar接管内置在Xalan实现中的JDK 1.6?
- 执行在java中通过网络发送的类文件
- 用于热类重新加载的各种Java插件之间有什么区别?哪一个最直观?
- Java类加载器:为什么首先搜索父类加载器?
- Tomcat6忽略web-inf / lib
- Java 9 – 在运行时动态添加jar
- 为什么Class.getPackage为来自不同包的类返回相同的包?
- loadClass(String name)和loadClass(String name,boolean resolve)之间的区别
- 修补或覆盖核心Java 10类的实现