-1

When creating a mutable class without using the final as in

public final class X {...}

but rather, just using a regular class declaration without final, as in

public class X {...}

and then using static factory constructor, with private constructor where all fields are private, then my question is - isn't it enough to just declare private fields without the final, as example

private double d;

or/why do I still have to say

private final double d;

the only answer I have is that I don't mistakenly mutate within the class any non final fields, but can anyone change from outside?

Basixp
  • 115
  • 6
  • 2
    There are thread-safety guarantees that come along with `final` that you won't get otherwise. – shmosel Jan 10 '18 at 21:09
  • 1
    https://stackoverflow.com/questions/146311/immutable-class-should-be-final – Oleksandr Pyrohov Jan 10 '18 at 21:21
  • If you make a normal class and require it's properties are assigned in a single constructor and use private properties and do not include any getters, then the class is mostly immutable. You don't get protections of final, but it works well enough in non-complex cases. public class MyClass { public MyClass(int id, String value) { this.id = id; this.value = value; } private int id; private String value; } – daddygames Jan 10 '18 at 21:28
  • 1
    `final class` and `final double` mean two entirely different things. `final class` says this class can't be subclassed. Using it **doesn't** "extend" that finality to the member variables within the class. `final double d` means that once a value is set for `d` it can never be changed (and your code must guarantee that it gets set at some point) – Stephen P Jan 10 '18 at 21:34

2 Answers2

-1

No one will be able to touch those values outside that class code regardless wether you add the final or not.

If you can is best to declare them as final as it does give to the compiler further clues as to how these behaves so that it can be a bit more aggressive optimizing the code. Also a final field is thread-safe whereas you could mess up the state of non-private fields in delay initialization.

My advice is that you always declare final as much as possible and don't do delay/lazy initialization unless there is a clear performance gain.

Also very important to keep in mind is that a final reference to an array or a non-immuatable object does not guarantee that its content won't be changed if you share the reference value (e.g. return it directly via a getter). There is no work around for naked arrays but for java.util.* collections you can always share a unmodifiable-wrapped reference to your collection (see Collections.unmodifiableXXXX methods) instead.

Finally notice that despite of declaring a field as private with or without final those value may still be changed using some funky low-level instrumentation (see this for example). However no-one should really be worried about this when programming.

Valentin Ruano
  • 2,726
  • 19
  • 29
  • 1
    The funky reflection code can be used to modify both `private` and `final` fields, so I don't see why it's relevant. – shmosel Jan 12 '18 at 09:29
  • @shmosel I think is relevant in the sense that I just noticing that virtually it is not possible to guarantee 100% immutability (although perhaps can be prevented changing the configuration of the security manager). Even if the question only considers wether ```final``` adds extra security or not I think is still relevant observation. In any case I didn't mean to imply that ```final``` would prevent that from happening. I guess I shall change the wording as to avoid such a interpretation or remove it all together. – Valentin Ruano Jan 12 '18 at 19:00
-1

A class being Immutable means that the class state and/or value(s) cannot be changed after an instance of that class has been created. Making a class immutable can be accomplished in several ways; using final variables can help, and making the class itself final can help by preventing subclassing where the subclass could break the rules of immutability.

The use of the final keyword on a class vs. using it on a variable mean two entirely different things.

Setting a class to be final means that class cannot be subclassed; that is, if you have

public final class X {...}

you can't extend it

public class Y extends X {...} // Illegal!

Whether or not a class is final has no bearing on the class member variables being final.

Setting a variable to be final, whether it's a static, a class member variable, or a local (to a method or a block) variable means that the variable can't be changed after it has been assigned a value.

Your code will also need to set a value to the final variable through any available execution path, so this is OK, because it always sets "max" to something:

...
final int max;
if (parameter) {
    max = 100;
} else {
    max = 1000;
}

but this will give you an error:

...
final int max;
if (parameter) {
    max = 100;
}

because it sets "max" if "parameter" evaluates to true but never sets "max" otherwise.
This will usually be done in a constructor for an immutable object:

public final class X
{
    final int value;
    public X(int v)
    {
        this.value = v;   // Now that `value` has been set
                          // it can never be changed
    }
}

Declaring a class as final does not imply anything about its class members being final, so your question "why do I still have to say" is because those two uses of final are unrelated.

Note that you can also declare a method to be final:

public final int getMax() {...}

This means that a subclass is not allowed to override this method with a new implementation. (final on a method makes no sense if the class is already final because there can't be any subclasses that attempt to override the method.)

Stephen P
  • 14,422
  • 2
  • 43
  • 67