2

I have an object:

Object obj = create(); 

... and I need to set some properties of this Object:

obj.setParam("7696969", 0x506); 

After this procedure I need to make sure that obj cannot be modified.

Is there a way to set obj as final without creating another final Object that copies obj?

8
  • 7
    You are looking for Immutable class. Commented Aug 22, 2013 at 20:37
  • 1
    Keep a boolean in your class that indicates if your data has been initialized yet. Check on it before setting the parameters and you're done. Commented Aug 22, 2013 at 20:39
  • 1
    A class Declared final do not means that couldn't be modified, just do not extended. Commented Aug 22, 2013 at 20:40
  • 1
    You have to do something like that: stackoverflow.com/a/3162682/2362664 Commented Aug 22, 2013 at 20:41
  • 1
    And a field declared final just means that the field can't be modified after initialization, not that any object the field addresses can't be modified. Commented Aug 22, 2013 at 20:43

5 Answers 5

11

Consider using the Builder design pattern for your newly created object.

FooBuilder builder = new FooBuilder(); builder.setParam(...); builder.setBar(...); final Foo myFoo = builder.build(); 

Note that even though myFoo is final, it's member fields may not be. You should not forget to declare those final as well.

Sign up to request clarification or add additional context in comments.

3 Comments

Note the type Foo here would need to be immutable if it shouldn't be modified.
+1, by the way, I think it is more elegant to use chain of calls for builders, e.g.: Foo myFoo = Foo.builder().withParam(...).withBar(...).build();
You might want to take a look at Lombok's Builder annotation. It's still marked as "experimental", but it's very close to make it to core.
3

The final keyword doesn't keep the internal variables of an object from being modified. All the final keyword does is keep a variable from being reassigned.

Keeping internals from being modified would require specific design of the object itself.

Objects whose inner variables cannot be reassigned are referred to as immutable objects. You can create an immutable object by using private access modifiers, and creating no set functions. Also be sure to declare all internal variables as final.

Amir's reference to the Builder design is a great suggestion. An immutable object with the builder pattern will work great for you.

4 Comments

For instance, the Java String and Integer classes (and numerous others) are immutable.
(Not really necessary to make the internal variables final, if you trust the person coding the immutable class.)
Very true @HotLicks but I don't trust myself to not forget one sleepy morning. I view the final keyword as protection against myself :)
I find I do some of my best programming in my sleep.
0

If you really need to set parameters separately through setters, then you'll have to do some simple algorithm. For instance, you can provide a boolean marking when the object must become immutable, set that boolean to true after your initialization procedure, all your setters will check for this boolean before deciding if they can reset current value with the new value.

When you don't have native mechanism doing the hard job for you, you have to think up an algorithm that'll do the job :)

Comments

0

You want an immutable class. Here's an example of one.

class Foo { private string s; private int i; public Foo(string s, int i) { this.s = s; this.i = i; } public string getS() { return s; } public int getI() { return i; } } 

The Builder design pattern is often overkill.

3 Comments

This only works if the constructor is the only way of setting a value. What if you don't know all values when the constructor is called, but rather they're added along the way?
For example, when you want to have a bidirectional reference.
Then something more sophisticated is required. It would depend on the scenario. I would just hate to leave OP with the impression that the Builder design pattern was required if all that is needed is an immutable.
0

Without using the Builder pattern what you can do is

 public class MyImmutableClass { final private String foo; final private String bar; public MyImmutableClass(String f, String b) { this.foo = f; this.bar = b; } // only getters } 

The way it work is

  1. make all fields final
  2. provide no setters
  3. make sure subclass can't override any method ( make the class final )

The builder pattern comes handy in case the number of params in the constructor increases. You are just using the builder to make your code more maintainable and readable but the strategy is almost same i.e it also permit object manipulation only through the inner static class and expose read only (getters) methods in the main/outer class

Another reason for using builder could be in a situation where your object has some mandatory as well as optional parameters.

 public class Item { // private fields & getters public static class Builder { // same private fields public Builder(String f, String b) { // set values } ... ... } } 

Here you can use the inner public Builder(String f, String b) constructor to take two mandatory parameters keeping the rest as optional

If the number of parameters is less I think the first strategy work much better than implementing builder, as it has the drawbacks of code duplication (builder needs to copy all fields from the outer class)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.