Why final keyword is necessary for immutable class?

后端 未结 7 1203
陌清茗
陌清茗 2020-12-08 01:17

Could you please clarify that why final keyword is required before class when we are making it an immutable one. I mean, if we declare all of it\'s attr

相关标签:
7条回答
  • 2020-12-08 01:54

    If an immutable class Foo is sealed ("final"), then anyone who receives a reference to a Foo may be assured that if Foo was implemented correctly, the referenced instance will in fact be immutable. If an immutable class is not sealed, then someone who receives a reference to a Foo may be assured that if the actual class of of the referenced object (which may be Foo or some derivative type implemented by some arbitrary unknown person) was implemented correctly, the instance will be immutable. Leaving Foo unsealed means that anyone who relies upon Foo to be immutable will have to trust that everyone who writes a class that derives from Foo will implement it correctly. If one wants to be certain that every reference to a Foo will in fact target an immutable instance without having to rely upon the authors of derivative classes to abide by the contract, making Foo final can aid in such assurance.

    On the other hand, the possibility that a class might derive from Foo but violate its immutability isn't terribly different from the possibility that a class which derives from any other class might violate the contracts of its parent class. Any code which accepts a reference of any type which can be subclasssed by outside code might be given an instance of a subclass which violates its parent's contract.

    The fundamental question when deciding whether an immutable class should be sealed is the same as for any other class: whether the benefits of leaving the type unsealed outweigh any dangers that would be posed by doing so. In some cases, it may make sense to have an extensible immutable class, or even an abstract class or interface whose concrete implementations are all contractually obligated to be immutable; for example, a drawing package might have an ImmutableShape class with some concrete fields, properties, and methods to define 2D transformations, but an abstract Draw method, allowing for the definition of derivative types ImmutablePolygon, ImmutableTextObject, ImmutableBezierCurve, etc. If someone implements an ImmutableGradientFilledEllipse class but fails to have that type make its own copy of a mutable GradientColorSelector, the colors of gradient-filled polygons might change unexpectedly, but that would be a fault of the ImmutableGradientFilledEllipse class, and not the consuming code. Despite the possibility of a broken implementation failing to uphold the "immutability" contract, an extensible ImmutableShape class would be much more versatile than a sealed one.

    0 讨论(0)
  • 2020-12-08 02:04

    You don't strictly need final to make an immutable class. i.e. you can make an immutable class without it being final.

    However, if you don't make it final, then it is possible for someone to extend a class and create a subclass that is mutable (either by adding new mutable fields, or overriding methods in a way that enables you to mutate protected fields of the original immutable class). This is a potential problem - it violates the Liskov Substitution Principle, in the sense that you would expect the property of immutablity to be preserved by all subtypes.

    Hence, it is usually good practice to make immutable classes final to avoid this risk.

    0 讨论(0)
  • 2020-12-08 02:06

    If all public and protected methods are final and none of them allows modifying private fields, and all public and protected fields are both final and immutable, then I guess it could be said class is semi-immutable, or sort of constant.

    But things break down when you create a subclass and need to override equals and hashcode. And can not because you made them final... So the whole thing is broken, so just make the whole class final to prevent programmer from being a fool by accident.

    As an alternative to doing this kind of bastardized version immutability, you have several options.

    If you want to attach extra data to immutable instance, use Map. Like if you wanted to add age to name, you would not do class NameAge extends String... :-)

    If you want to add methods, create a class of static utility functions. That is a bit klunky, but it is the current Java way, Apache commons for example is full of such classes.

    If you want to add extra methods and data, create a wrapper class with delegate methods to methods of the immutable class. Anybody needing to use the extra methods needs to be aware of them anyway, and there is not much practical difference in casting to derived non-immutable class or doing something like new MyWrapper(myImmutableObj) for many use cases.

    When you really have to have reference to original imutable object (like storing it in existing class you can not change), but need the extra data somewhere, you need to use the Map approach to keep the extra data around, or something like that.

    0 讨论(0)
  • 2020-12-08 02:09

    An immutable object is an object which state is guaranteed to stay identical over its entire lifetime. While it is perfectly possible to implement immutability without final, its use makes that purpose explicit, to the human (the software developer) and the machine (the compiler).

    Immutable objects carry some very desirable characteristics:

    they are simple to understand and easy to use
    they are inherently thread-safe: they require no synchronization
    they make great building blocks for other objects 
    

    Clearly final is going to help us define immutable objects. First in labelling our object as immutable, which makes it simple to use and understand by other programmers. Second in guaranteeing that the object's state never changes, which enable the thread-safe property: thread concurrency issues are relevant when one thread can change data while another thread is reading the same data. Because an immutable object never changes its data, synchronizing access to it is not needed.

    Create an immutable class by meeting all of the following conditions:

    Declare all fields private final.
    Set all fields in the constructor.
    Don't provide any methods that modify the state of the object; provide only getter methods (no setters).
    Declare the class final, so that no methods may be overridden.
    Ensure exclusive access to any mutable components, e.g. by returning copies.
    

    A class declared final cannot be sub classed. Other classes cannot extend final class. It provides some benefit to security and thread safety.

    0 讨论(0)
  • 2020-12-08 02:10

    A class that is declared final cannot be subclassed. See also http://docs.oracle.com/javase/tutorial/java/IandI/final.html

    The different semantics of all uses of the final keyword are described in the The Java Language Specification

    • 4.12.4 final Variables Page 80
    • 8.1.1.2 final Classes Page 184
    • 8.3.1.2 final Fields Page 209
    • 8.4.3.3 final Methods Page 223
    0 讨论(0)
  • 2020-12-08 02:10

    'final' as the keyword's name suggest means that the attribute to which final keyword is attached can't be changed(in terms of value) in other words it behaves like a constant.

    As per your question if all members of the class is made private and final but the class is not made final then the same class can be inherited but the super class member are immutable as final keyword is attached to them.

    0 讨论(0)
提交回复
热议问题