1

In a class, I am declaring a field that does not change from the assignment onwards. This field (or constant, to be precise) is also shared by all instances of the class.

For the two reasons above, I am using the

final

and

static

keywords when declaring the constant.

However, since, I am using both final and static, I need to assign a value at the declaration, because the constant is assigned its value when the class is loaded. Unfortunately, in this case, this cannot be done because that value is not known to the program from the beginning but only when the class is instantiated (because its value is figured out by the program). It must, therefore, be assigned its value within the constructor of the class based on a parameter passed to it.

As previously said, this is illegal in java.

I do not know how to solve the problem. Everything suggests that I should use both static and final, because the field is shared by all instances of the class and does not change from the moment a value is assigned to it.

Moreover, according to Android documentation, usage of the final keyword has the following advantage:

accesses to [a final field] will use a relatively inexpensive "string constant" instruction instead of a field lookup.

Additionally, usage of the static keyword has the advantage that only one field is used for all instances instead of one field per instance.

It is therefore highly important that I be able to use both those keywords for performance reasons.

Summing up: I need to use both final and static but, because the value of the constant is not known at class load-up, I cannot do it. Is there a workaround so that I can still use final and static for my constant?

bkr879
  • 2,035
  • 2
  • 15
  • 23
  • 1
    Can you do it in the static initializer or have a static method that provides the value? – Cinnam Sep 14 '15 at 02:12
  • I think you need an immutable object [http://stackoverflow.com/questions/279507/what-is-meant-by-immutable][1] [1]: http://stackoverflow.com/questions/279507/what-is-meant-by-immutable – Cassian Sep 14 '15 at 02:38
  • 1
    A constant is known at compilation time, or can be derived from other constants at compilation time. In Java, they are represented as `static final` fields. If you don't know its value in compilation time, then it's not a constant. Just use a common `static` field instead. – fps Sep 14 '15 at 20:34

3 Answers3

3

Nope. If a static field is final, then it has to either be initialized inline:

public static final String CONSTANT = "blah";

or in a static initializer:

public static final String CONSTANT;
static {
    CONSTANT = "blah";
}

On how to solve it, this sounds like an odd design where you want to initialize the value in a constructor, but it's used by all instances. What happens when a second instance is constructed? Is the value of that parameter just ignored?

adashrod
  • 456
  • 2
  • 12
2

Use a singleton!

The idea here is to use a singleton object to hold a single instance. That instance can be created at runtime whenever you need it to be created.

You can have the instance be whatever you'd like. Once initialized, it cannot be changed again. Final, Static, and initializable after runtime.

You can read up a bit on how to use singletons here.

Edit:

As pointed out in the comments, be sure to know the drawbacks of singletons as well. If you're interested, there is a popular post that has more information.

Community
  • 1
  • 1
  • 1
    But first read here: [What's so bad about singletons?](http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons) I think their drawback often outweigh their benefits, especially if you ever find yourself testing code that has a dependency on a singleton. – Tobia Tesan Sep 14 '15 at 20:34
  • @TobiaTesan Yeah, Spring singleton beans are soooo bad... Whether singletons are good or bad, it is debatable and subject to analysis on a per-case basis. There are no absolute rules in software. – fps Sep 14 '15 at 20:40
  • @FedericoPeraltaSchaffner who ever said otherwise? :-) I still think it is important to point out that the pattern has drawbacks (or, more appropriately, that there are *situations* when it is not a good idea) to counterbalance OP's suggestion and make sure it isn't followed blindly. – Tobia Tesan Sep 14 '15 at 20:48
  • 1
    @TobiaTesan You're right, my comment might have been a little bit too harsh. I apologize if that was the case. I agree to your concerns regarding the singleton pattern. It's just that sometimes it's very useful, despite its drawbacks ;) – fps Sep 14 '15 at 22:03
  • I realize this was two weeks ago, but thank you for adding that link to the drawbacks of singletons. I'm going to include a link to that in my answer for future readers, just so that it's not glanced over in the comments. :) –  Sep 28 '15 at 15:11
-1

I recommend you replace your static constants by static methods, because you actually need to control wether a certain value has already been initialized or not:

public final class MyConstants
{
    private MyConstants(){}

    private static <type> constant1;

    public static void setConstant1(<type> value)
    {
        if (constant1==null)
        {
            throw new IllegalStateException("Constant1 clready initialized");
        }
        else
        {
            constant1=value;
        }
    }

    public static <type> getConstant1()
    {
        if (constant1==null)
        {
            throw new IllegalStateException();
        }
        return constant1;
    }
}

In this way, you add a protocol to your constants class: The constant must be initialized once -and just once- prior to the first time it is used.

Little Santi
  • 8,563
  • 2
  • 18
  • 46