61

In Java, it's taught that variables should be kept private to enable better encapsulation, but what about static constants? This:

public static final int FOO = 5;

Would be equivalent in result to this:

private static final int FOO = 5;
...
public static getFoo() { return FOO; }

But which is better practice?

Chris Cummins
  • 935
  • 1
  • 8
  • 12
  • 1
    Voting to close on not constructive (based on the opinionated feedback already offered). Is `FOO` really a constant? Is the class providing `FOO` part of an API? Or part of an end point application? There are mathematical constants which never change. There are also bit flags that should never change (see SWT). So the answer is "It depends." – Tim Bender Apr 06 '12 at 18:57

7 Answers7

76

There's one reason to not use a constant directly in your code.

Assume FOO may change later on (but still stay constant), say to public static final int FOO = 10;. Shouldn't break anything as long as nobody's stupid enough to hardcode the value directly right?

No. The Java compiler will inline constants such as Foo above into the calling code, i.e. someFunc(FooClass.FOO); becomes someFunc(5);. Now if you recompile your library but not the calling code you can end up in surprising situations. That's avoided if you use a function - the JIT will still optimize it just fine, so no real performance hit there.

Voo
  • 29,040
  • 11
  • 82
  • 156
  • 5
    Interesting, I never realized this. I never come across constants with getters in the wild though. – Adriaan Koster Apr 06 '12 at 21:03
  • Thanks for the info, it seems then that private constants and getters are empirically safer choices and should be considered better practice. – Chris Cummins Apr 07 '12 at 14:18
  • 4
    @Chris Depends on what your constants are - there are lots of constants that are set in stone (`Pi` for example is quite unlikely to turn out to be 3 after all these years ;) ) so I wouldn't condemn the use of public constants in all cases. But one should keep this in mind, because debugging such a problem is extremely horrible. – Voo Apr 07 '12 at 17:21
  • 2
    Wow! +10! I've been in the business for longer than I care to mention, and I've always wondered why I shouldn't just use a public constant when it seems safe to do so! – Stephen Hosking Nov 13 '12 at 23:15
  • It's an old post but still very relevant. IMO *constants should never change their value*. That's why they are called constants. If there is any field that is used to share it's value across classes, and it's value can be changed, it should not be called constant and should not be treated as such. Java inlining the constants assumes that the value is no going to change. For more info, refer to https://stackoverflow.com/a/2338074/841221 – Aakash Jun 07 '17 at 09:14
  • 1
    Excuse me, my English is not very good, I didn't see the correct conclusion. Someone told me what the correct answer should be? – 袁文涛 Mar 06 '19 at 03:03
  • 3
    @TJ If the "constant" could change in the future use a getter. If the constant will always be the same you can use a public const. – Voo Mar 06 '19 at 09:31
10

Since a final variable cannot be changed later if you gonna use it as a global constant just make it public no getter needed.

Serdar Dogruyol
  • 5,147
  • 3
  • 24
  • 32
  • 9
    Only if you're absolutely certain you'll never change the final variable though. constants are inlined by the compiler which can lead to extremely surprising results if they change later on and you don't recompile everything. Edit: Figured, that's worth an answer to make it a bit more prominently. – Voo Apr 06 '12 at 18:51
7

Getter is pointless here and most likely will be inlined by the JVM. Just stick with public constant.

The idea behind encapsulation is to protect unwanted changes of a variable and hide the internal representation. With constants it doesn't make much sense.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
4

Use the variales outside the class as:

public def FOO:Integer = 5; 

If you encapsulation is not your priority. Otherwise use the second variant so that you expose a method and not the variable.

private static final int FOO = 5;
...
public static getFoo() { return FOO; }

Is also a better practice for code maintenance to not rely on variables. Remember that "premature optimization is the root of all evil".

profimedica
  • 2,716
  • 31
  • 41
1

The first one if the getFoo result is costant and not need to be evaluated at runtime.

dash1e
  • 7,677
  • 1
  • 30
  • 35
1

I'd stay with the getFoo() since it allows you to change the implementation in the future without changing the client code. As @Tomasz noted, the JVM will probably inline your current implementation, so you pay much of a performance penalty.

shams
  • 3,460
  • 24
  • 24
0

The advantage of using setter and getter on member is to be able to overwrite. This is not valid for static "methods" (rather functions)

There also no way to define interfaces static methods.

I would go with the field access

stefan bachert
  • 9,413
  • 4
  • 33
  • 40