声明变量final和static

时间:2014-10-07 17:31:27

标签: java classloader

此评论是在代码审核中完成的,而制作该评论的人已不在我们的团队中。

  

在运行时必须由类加载器解析的任何类型都不应该具有被声明为final和static的引用保存的实例。

以下是代码行:

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

我熟悉声明loggers静态或非静态的争论,但这个评论似乎更为通用。我找不到为什么静态和最终都不好的任何解释。有人可以详细说明吗?

2 个答案:

答案 0 :(得分:13)

评论很可能与 Classloader Leaking here is a good article)的问题有关。

简而言之,这个问题发生在需要重新加载类加载器的环境中。如果通过类加载器动态加载类,然后尝试重新加载类加载器,则使用通过此类加载器创建的类的对象保留静态最终字段将阻止卸载类加载器本身。一旦发生这种情况,您将获得OutOfMemoryError

上面链接的文章列出了可能产生此行为的主要罪魁祸首之间的日志库,以及可以解决泄漏问题的措施(例如明确释放类加载器)。

答案 1 :(得分:12)

代码行完全正常,并且没有真正的问题,因为变量是finalstatic

发表评论的人可能会对以下内容感到困惑。

在Java中,当您创建类型为public final static的{​​{1}}变量时(例如;它也适用于其他一些类型),编译器可能会在您使用该变量的地方替换它实际的常量值而不是对变量的引用。例如,假设您有以下内容:

int

当你编译并运行它时,它显然会打印3。

现在假设您更改了课程class A { public final static int VALUE = 3; } public class B { public static void main(String[] args) { System.out.println(A.VALUE); } } 并设置了A。如果您重新编译类VALUE = 4然后运行类A(不重新编译类B),您会看到B。但是,你会看到4。这是因为当您编译类3时,类A.VALUE中的B被实际的常量值3替换。

这是Java编译器为常量所做的优化。

正如您所看到的,如果在类的公共API中有这样的常量,这可能会导致问题。如果更改此类常量的值,代码的用户将不得不重新编译代码。

但是在您在问题中发布的代码中,这不是问题,因为变量是B

更多详情:

Java Language Specification 13.4.9