Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring variable final and static

Tags:

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.

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. I can't find any explanations of why static and final are bad. Can somebody elaborate?

like image 978
sdoca Avatar asked Oct 07 '14 17:10

sdoca


People also ask

How do you declare a final static variable?

Static variables are normally declared as constants using the final keyword. Constants are variables that are declared as public/private, final, and static. Constant variables never change from their initial value.

Why should a variable be declared as static and final?

Declaring variables only as static can lead to change in their values by one or more instances of a class in which it is declared. Declaring them as static final will help you to create a CONSTANT. Only one copy of variable exists which can't be reinitialize.

Should final variables be static?

No, absolutely not - and it's not a convention. static and final are entirely different things. static means that the field relates to the type rather than any particular instance of the type. final means that the field can't change value after initial assignment (which must occur during type/instance initialization).

Can we declare variable as static?

Class variables also known as static variables are declared with the static keyword in a class, but outside a method, constructor or a block. There would only be one copy of each class variable per class, regardless of how many objects are created from it.


2 Answers

The comment is most likely related to a problem of Classloader Leaking (here is a good article).

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.

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).

like image 197
Sergey Kalinichenko Avatar answered Nov 05 '22 06:11

Sergey Kalinichenko


The line of code is perfectly fine, and there is no real problem because the variable is final and static.

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. 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.

Now suppose that you change class A and set VALUE = 4. You would expect that if you recompile class A and then run class B (without recompiling class B), you would see 4. But what happens is that you will still see 3. That is because the A.VALUE in class B was replaced by the actual constant value 3 when you compiled class B.

This is an optimization that the Java compiler does for constants.

As you can see this can cause problems, if you have such constants in the public API of your classes. 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.

More details:

Java Language Specification 13.4.9

like image 30
Jesper Avatar answered Nov 05 '22 05:11

Jesper