简体   繁体   English

声明变量final和static

[英]Declaring variable final and static

This comment was made in a code review and the person who made it is no longer on our team. 此评论是在代码审核中进行的,而制作该评论的人不再在我们的团队中。

Any type that must be resolved by the classloader at runtime should never have instances which are held by references declared to be both final and static. 在运行时必须由类加载器解析的任何类型都不应该具有被声明为final和static的引用保持的实例。

Here's the line of code: 这是代码行:

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

I'm familiar with the debate of declaring loggers static or non-static, but this comment seems to be more general. 我熟悉声明loggers静态或非静态的争论,但这个评论似乎更为通用。 I can't find any explanations of why static and final are bad. 我找不到为什么静态和最终都不好的任何解释。 Can somebody elaborate? 有人可以详细说明吗?

The comment is most likely related to a problem of Classloader Leaking ( here is a good article ). 评论很可能与Classloader Leaking的问题有关( 这是一篇好文章 )。

In a nutshell, this problem happens in environments where classloader needs to be reloaded. 简而言之,这个问题发生在需要重新加载类加载器的环境中。 If you load a class dynamically through a classloader and then try reloading the classloader, keeping static final fields with objects of classes created through this classloader will prevent unloading the classloader itself. 如果通过类加载器动态加载类,然后尝试重新加载类加载器,则使用通过此类加载器创建的类的对象保留静态最终字段将阻止卸载类加载器本身。 Once this happens, you get an OutOfMemoryError . 一旦发生这种情况,您将获得OutOfMemoryError

The article linked above lists logging libraries among the top culprits that could produce this behavior, along with measures you can take to work around the leaks (such as releasing classloaders explicitly). 上面链接的文章列出了可能产生此行为的顶级罪魁祸首之间的日志库,以及可以用来解决泄漏的措施(例如显式释放类加载器)。

The line of code is perfectly fine, and there is no real problem because the variable is final and static . 代码行非常精细,并且没有真正的问题,因为变量是finalstatic

Maybe the person who made that comment was confused by the following. 也许发表评论的人对以下内容感到困惑。

In Java, when you create a public final static variable of type int (for example; it also works with some other types), then the compiler might, in places where you use that variable, substitute the actual constant value instead of a reference to the variable. 在Java中,当您创建int类型的public final static变量时(例如;它也适用于其他一些类型),那么编译器可能会在您使用该变量的位置替换实际常量值而不是引用变量。 For example, suppose you have the following: 例如,假设您有以下内容:

class A {
    public final static int VALUE = 3;
}

public class B {
    public static void main(String[] args) {
        System.out.println(A.VALUE);
    }
}

When you compile and run this, it will obviously print 3. 当你编译并运行它时,它显然会打印3。

Now suppose that you change class A and set VALUE = 4 . 现在假设您更改了A类并设置了VALUE = 4 You would expect that if you recompile class A and then run class B (without recompiling class B ), you would see 4 . 你会期望如果你重新编译A类然后运行B类(不重新编译B类),你会看到4 But what happens is that you will still see 3 . 但是会发生什么,你仍然会看到3 That is because the A.VALUE in class B was replaced by the actual constant value 3 when you compiled class B . 这是因为A.VALUEB是由实际的恒定值替换3 ,当你编译的类B

This is an optimization that the Java compiler does for constants. 这是Java编译器为常量所做的优化。

As you can see this can cause problems, if you have such constants in the public API of your classes. 如您所见,这可能会导致问题,如果您在类的公共API中有这样的常量。 Users of your code will have to recompile their code if you change the value of such constants. 如果更改此类常量的值,代码的用户将不得不重新编译代码。

But in the code you posted in your question this is not a problem, because the variable is private . 但是在您在问题中发布的代码中,这不是问题,因为变量是private

More details: 更多细节:

Java Language Specification 13.4.9 Java语言规范13.4.9

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM