0

Well, I've a final property but I don't want to initialize it when I create my object because I can't. So I tried to not initialize it in my constructor but using a setter, I guessed it would have been something like a only-one-time usable setter, but I've this error :

Test.java:27: error: cannot assign a value to final variable foo

    this.foo = new String(foo);

Here is a short code I used to test this :

class Test {

    private final String foo;

    public static void main(String[] args) {
        Test test = new Test();
        test.setFoo("gygygy");
        System.out.println(test.getFoo());
    }

    public Test() {
        System.out.println("Constructor");
    }

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

}

So I assume the constructor implicitly makes something like this.foo = new String(); or this.foo = null; and I think I can't modify this behavior, but how can I have an equivalent to what I wanna do ? I think in something like :

private String foo;

/* ... */

public void setFoo(String foo) {
    if( !(this.foo.isInitialized()) )
        this.foo = foo;
}

but the Object.isInitialized() method obviously doesn't exist, and I can't find an equivalent x)

So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.

Thanks !

Community
  • 1
  • 1
Thiht
  • 252
  • 4
  • 11

3 Answers3

2

You can add a boolean field isInisialized but the best option is to pass the value in the constructor (possibly using a Builder pattern if you need to)

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Well I'll simply use the solution of the boolean, thanks ! I didn't know the builder pattern. I think I understand how it works but I prefer the first solution, it'll be implemented faster and more easy to use for a single attribute :p – Thiht Jul 22 '12 at 16:51
1

So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.

You simply can't do that. All you can do is have a separate field which you also update to note once you've set the "real" field - and if you try to set it a second time, throw an exception.

Alternatively, make your type immutable, but give it a method which constructs a new instance of the class, with the same data as before except the single new value, e.g.

public Test withFoo(String newFoo) {
    // Call a private constructor here, passing in the other fields from
    // "this", and newFoo for the value of foo
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This method can be called more than one time, so it's exactly the same as if my attribute isn't final if I didn't misunderstood – Thiht Jul 22 '12 at 16:57
  • @Thiht: The method would return a *new* object... the field would be set in the constructor, so it could be final. – Jon Skeet Jul 22 '12 at 17:32
  • Oh okay I see. Well, thanks for this answer, it should also work in this case. – Thiht Jul 22 '12 at 18:29
0

Rule says a final instance member variable should be initialized at the very place where it is declared or within the constructor. By this rule, your requirement cannot be satisfied with your piece of code as is. You can use a builder pattern to achieve it. See this link Builder Pattern in Effective Java

Community
  • 1
  • 1
devang
  • 5,376
  • 7
  • 34
  • 49