Are all final class immutable? - java

Are all final classes in Java immutable.
String and Integer both are final classes and both are immutable i beleive.

No, final means the class can not be extended. It says nothing about mutability. For example:
final class MutInt {
public int modifyMe;
}

No - a final class means you cannot inherit from it. It has nothing to do with mutability. The following class is final yet mutable:
public final class FinalMutable {
int value;
public void setValue(int v) { value=v; }
public int getValue() { return value; }
}

There is no keyword for immutability, it's more like a design pattern.
EDIT:
This means, there is no keyword, that makes a class immutable. To make a class immutable, you have to protect the internals by make them final or private.
The confusing thing is this: The final keyword has different meanings when used on a class then it has when used on a field/variable. The former means "this class can not be extended". The Second means "this variable (or reference) can not be changed".

Further to the other responses, if you look at the code for java.lang.String you'll see it contains a field: hash, which is mutable and is in fact computed and stored when hashCode() is called for the first time.
However, the class is still immutable: The hash field cannot be accessed directly or modified outside of the class.
Also, you may notice a common approach within the JDK is the implementation of immutable wrappers that can be used to expose an object's internal state without allowing it to be modified; e.g.
private final List<String> values;
public List<? get String> getValues() {
return Collections.unmodifiableList(values);
}

As has been said by the others before final does not make a class imuutable in Java though it plays a part in the immutability strategy. To obtain immutability you should follow the general guidlines:
ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
make fields private and final
force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention)
do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
if the class has any mutable object fields, then they must be defensively copied when passed between the class and its caller

The private field can't be accessed by sub class's overridden methods...So there is no way the sub class methods change the private field of super class...Then what is the use of making the immutable class as final?

Final keywords prevents the other classes to inherit it. Final keyword doesn't make it immutable but there are such condition as making the instance class members private as well final and by using getters and not using setters

A final immutable classes cannot be mutated. Here below it shows a non-final immutable class being mutated:
// a class not intended to be mutated
public class GoodClass{
private String name;
public GoodClass() {
this.name = "Good Class Neme";
}
public String getName() {
return name;
}
}
public class BadClass extends GoodClass {
private String name;
public String getName() {
return name;
}
// mutating state
public void setName(String name) {
this.name = name;
}
}

Related

Why is Public class immutable? [duplicate]

I read that to make a class immutable in Java, we should do the following,
Do not provide any setters
Mark all fields as private
Make the class final
Why is step 3 required? Why should I mark the class final?
If you don't mark the class final, it might be possible for me to suddenly make your seemingly immutable class actually mutable. For example, consider this code:
public class Immutable {
private final int value;
public Immutable(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Now, suppose I do the following:
public class Mutable extends Immutable {
private int realValue;
public Mutable(int value) {
super(value);
realValue = value;
}
public int getValue() {
return realValue;
}
public void setValue(int newValue) {
realValue = newValue;
}
public static void main(String[] arg){
Mutable obj = new Mutable(4);
Immutable immObj = (Immutable)obj;
System.out.println(immObj.getValue());
obj.setValue(8);
System.out.println(immObj.getValue());
}
}
Notice that in my Mutable subclass, I've overridden the behavior of getValue to read a new, mutable field declared in my subclass. As a result, your class, which initially looks immutable, really isn't immutable. I can pass this Mutable object wherever an Immutable object is expected, which could do Very Bad Things to code assuming the object is truly immutable. Marking the base class final prevents this from happening.
Contrary to what many people believe, making an immutable class final is not required.
The standard argument for making immutable classes final is that if you don't do this, then subclasses can add mutability, thereby violating the contract of the superclass. Clients of the class will assume immutability, but will be surprised when something mutates out from under them.
If you take this argument to its logical extreme, then all methods should be made final, as otherwise a subclass could override a method in a way that doesn't conform to the contract of its superclass. It's interesting that most Java programmers see this as ridiculous, but are somehow okay with the idea that immutable classes should be final. I suspect that it has something to do with Java programmers in general not being entirely comfortable with the notion of immutability, and perhaps some sort of fuzzy thinking relating to the multiple meanings of the final keyword in Java.
Conforming to the contract of your superclass is not something that can or should always be enforced by the compiler. The compiler can enforce certain aspects of your contract (eg: a minimum set of methods and their type signatures) but there are many parts of typical contracts that cannot be enforced by the compiler.
Immutability is part of the contract of a class. It's a bit different from some of the things people are more used to, because it says what the class (and all subclasses) can't do, while I think most Java (and generally OOP) programmers tend to think about contracts as relating to what a class can do, not what it can't do.
Immutability also affects more than just a single method — it affects the entire instance — but this isn't really much different than the way equals and hashCode in Java work. Those two methods have a specific contract laid out in Object. This contract very carefully lays out things that these methods cannot do. This contract is made more specific in subclasses. It is very easy to override equals or hashCode in a way that violates the contract. In fact, if you override only one of these two methods without the other, chances are that you're violating the contract. So should equals and hashCode have been declared final in Object to avoid this? I think most would argue that they should not. Likewise, it is not necessary to make immutable classes final.
That said, most of your classes, immutable or not, probably should be final. See Effective Java Second Edition Item 17: "Design and document for inheritance or else prohibit it".
So a correct version of your step 3 would be: "Make the class final or, when designing for subclassing, clearly document that all subclasses must continue to be immutable."
Don't mark the entire class final.
There are valid reasons for allowing an immutable class to be extended as stated in some of the other answers so marking the class as final is not always a good idea.
It's better to mark your properties private and final and if you want to protect the "contract" mark your getters as final.
In this way you can allow the class to be extended (yes possibly even by a mutable class) however the immutable aspects of your class are protected. Properties are private and can't be accessed, getters for these properties are final and cannot be overridden.
Any other code that uses an instance of your immutable class will be able to rely on the immutable aspects of your class even if the sub class it is passed is mutable in other aspects. Of course, since it takes an instance of your class it wouldn't even know about these other aspects.
If you do not make it final I can extend it and make it non mutable.
public class Immutable {
privat final int val;
public Immutable(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
public class FakeImmutable extends Immutable {
privat int val2;
public FakeImmutable(int val) {
super(val);
}
public int getVal() {
return val2;
}
public void setVal(int val2) {
this.val2 = val2;
}
}
Now, I can pass FakeImmutable to any class that expects Immutable, and it will not behave as the expected contract.
If it's not final then anyone could extend the class and do whatever they like, like providing setters, shadowing your private variables, and basically making it mutable.
That constraints other classes extending your class.
final class can't be extended by other classes.
If a class extend the class you want to make as immutable, it may change the state of the class due to inheritance principles.
Just clarify "it may change". Subclass can override superclass behaviour like using method overriding (like templatetypedef/ Ted Hop answer)
For creating an immutable class it is not mandatory to mark the class as final.
Let me take one such example from the standard library itself: BigInteger is immutable but it's not final.
Actually, immutability is a concept according to which once an object is created, it can not be modified.
Let's think from the JVM point of view. From the JVM point of view, an object of this class should be fully constructed before any thread can access it and the state of the object shouldn't change after its construction.
Immutability means there is no way to change the state of the object once it is created and this is achieved by three thumb rules which make the compiler recognize that class is immutable and they are as follows:
All non-private fields should be final
Make sure that there is no method in the class that can change the fields of the object either directly or indirectly
Any object reference defined in the class can't be modified from outside of the class
For more information refer to this URL.
Let's say you have the following class:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class PaymentImmutable {
private final Long id;
private final List<String> details;
private final Date paymentDate;
private final String notes;
public PaymentImmutable (Long id, List<String> details, Date paymentDate, String notes) {
this.id = id;
this.notes = notes;
this.paymentDate = paymentDate == null ? null : new Date(paymentDate.getTime());
if (details != null) {
this.details = new ArrayList<String>();
for(String d : details) {
this.details.add(d);
}
} else {
this.details = null;
}
}
public Long getId() {
return this.id;
}
public List<String> getDetails() {
if(this.details != null) {
List<String> detailsForOutside = new ArrayList<String>();
for(String d: this.details) {
detailsForOutside.add(d);
}
return detailsForOutside;
} else {
return null;
}
}
}
Then you extend it and break its immutability.
public class PaymentChild extends PaymentImmutable {
private List<String> temp;
public PaymentChild(Long id, List<String> details, Date paymentDate, String notes) {
super(id, details, paymentDate, notes);
this.temp = details;
}
#Override
public List<String> getDetails() {
return temp;
}
}
Here we test it:
public class Demo {
public static void main(String[] args) {
List<String> details = new ArrayList<>();
details.add("a");
details.add("b");
PaymentImmutable immutableParent = new PaymentImmutable(1L, details, new Date(), "notes");
PaymentImmutable notImmutableChild = new PaymentChild(1L, details, new Date(), "notes");
details.add("some value");
System.out.println(immutableParent.getDetails());
System.out.println(notImmutableChild.getDetails());
}
}
Output result will be:
[a, b]
[a, b, some value]
As you can see while original class is keeping its immutability, child classes can be mutable. Consequently, in your design you cannot be sure that the object you are using is immutable, unless you make your class final.
Suppose the following class were not final:
public class Foo {
private int mThing;
public Foo(int thing) {
mThing = thing;
}
public int doSomething() { /* doesn't change mThing */ }
}
It's apparently immutable because even subclasses can't modify mThing. However, a subclass can be mutable:
public class Bar extends Foo {
private int mValue;
public Bar(int thing, int value) {
super(thing);
mValue = value;
}
public int getValue() { return mValue; }
public void setValue(int value) { mValue = value; }
}
Now an object that is assignable to a variable of type Foo is no longer guaranteed to be mmutable. This can cause problems with things like hashing, equality, concurrency, etc.
Design by itself has no value. Design is always used to achieve a goal. What is the goal here? Do we want to reduce the amount of surprises in the code? Do we want to prevent bugs? Are we blindly following rules?
Also, design always comes at a cost. Every design that deserves the name means you have a conflict of goals.
With that in mind, you need to find answers to these questions:
How many obvious bugs will this prevent?
How many subtle bugs will this prevent?
How often will this make other code more complex (= more error prone)?
Does this make testing easier or harder?
How good are the developers in your project? How much guidance with a sledge hammer do they need?
Say you have many junior developers in your team. They will desperately try any stupid thing just because they don't know good solutions for their problems, yet. Making the class final could prevent bugs (good) but could also make them come up with "clever" solutions like copying all these classes into a mutable ones everywhere in the code.
On the other hand, it will be very hard to make a class final after it's being used everywhere but it's easy to make a final class non-final later if you find out you need to extend it.
If you properly use interfaces, you can avoid the "I need to make this mutable" problem by always using the interface and then later adding a mutable implementation when the need arises.
Conclusion: There is no "best" solution for this answer. It depends on which price you're willing and which you have to pay.
The default meaning of equals() is the same as referential equality. For immutable data types, this is almost always wrong. So you have to override the equals() method, replacing it with your own implementation. link

Understanding private fields in java [duplicate]

How is the compiler not complaining when I write the following code?
public class MyClass
{
private int count;
public MyClass(int x){
this.count=x;
}
public void testPrivate(MyClass o){
System.out.println(o.count);
}
}
Even though it is an instance of the same class in which testPrivate is written, shouldn't it give a compilation error at System.out.println(o.count)? After all, I am trying to access a private variable directly.
The code even runs fine.
A private member is accessible from any method within the class in which it is declared, regardless of whether that method accesses its own (this) instance's private member or some other instance's private member.
This is stated in JLS 6.6.1:
...Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
This feature of Java allows you to write methods that accept an instance of the class as an argument (for example - clone(Object other), compareTo(Object other)) without relying on the class having non private getters for all the private properties that need to be accessed.
Private fields are private to the class as a whole, not just to the object.
Other classes do not know that MyClass has a field called count; however, A MyClass object knows that another MyClass object has the count field.
Accessors are not security! They are encapsulation, to keep others from having to know about the code.
Consider if someone wrote a Quantum Bogo Sort, but disappeared once he quashed the last bug -- understanding the code causes one to be either deleted from the universe or to go mad.
Despite this minor drawback, if properly encapsulated, this should become your prefered sorting algorithm, as all fields and methods except Sort should be private.
You don't know how it works, and you don't want to know how it works, but it works and that's enough. If on the other hand, everything is public, and you have to understand how it does what it does to use it correctly -- that's just too much bother, I'll stick with quicksort.
Though it is the instance of the same class in which testPrivate is
written, but shouldn't it through a compiler error at
System.out.println(o.count);
No. It will never throw a compilation error.
This is much similar to what a simple getter and setter does or a copy constructor does. Remember we can access private members using this.
public MyClass {
private String propertyOne;
private String propertyTwo;
// cannot access otherObject private members directly
// so we use getters
// But MyClass private members are accessible using this.
public MyClass(OtherClass otherObject) {
this.propertyOne = otherObject.getPropertyOne();
this.propertyTwo = otherObject.calculatePropertyTwo();
}
public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
public String getPropertyOne() {
return this.propertyOne;
}
}
Your testPrivate method accepts an instance of MyClass. Since testPrivate is a method inside MyClass, it will have access to private properties.
public void testPrivate(MyClass o) {
this.propertyOne = o.propertOne;
}
Methods defined inside the class will always have access to it's private members, through this. and instance variable.
But if you define testPrivate outside of MyClass then, you won't have access to private members. There you will have to use a method or a setter or a getter.
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Check the official documentation

Are there any patterns for implementing mutable and immutable versions of a holder object?

In my application I have few types of holder objects, which primary purpose is to store heterogeneous related data. Their lifecycles can be divided into two parts:
Collecting data as soon as it becomes available;
Providing read-only access to stored data for the rest of a holder's life.
It is very tempting to make the holders immutable, but the data is not available at one time to be passed to a constructor. The simplest workaround I see is to make two versions of a holder class, one being mutable, and another being not:
public class MutableHolder {
public int field1;
public String field2;
// ...
public Object fieldN;
}
public class Holder {
public final int field1;
public final String field2;
// ...
public final Object fieldN;
public Holder(MutableHolder mutableHolder) {
this.field1 = mutableHolder.field1;
this.field2 = mutableHolder.field2;
// ...
this.fieldN = mutableHolder.fieldN;
}
}
However, I feel that this approach is violating the DRY principle (I must not forget to update both classes' fields as well as the constructor if I want to change anything) and is error prone. So here is my question: are there any existing patterns that I'm not aware of for implementing both mutable and immutable versions of a holder object?
Edit
I've suddenly found out that the code above is a very barebone version of the Builder pattern (see this or this). This makes me think that in this case DRY violation is considered acceptable.
I also have been stumbling over this for a while. Here is a design pattern I have come up with that I have not seen elsewhere.
public class Bob
{
// member variables
private int value;
// simple constructor
private Bob()
{
value(0);
}
// constructor with value
private Bob(int value)
{
value(value);
}
// get value
public final int value()
{
return this.value;
}
// set value
private final void value(int value)
{
this.value = value;
}
// mutable class modifies base class
public static class Mutable extends Bob
{
// simple constructor
private Mutable()
{
super();
}
// constructor with value
private Mutable(int value)
{
super(value);
}
// set value
public final void value(int value)
{
super.value(value);
}
}
// factory creator for immutable
public static final Bob immutable(int value)
{
return new Bob(value);
}
// factory creator for mutable
public static final Mutable mutable()
{
return new Mutable();
}
// another mutable factory creator
public static final Mutable mutable(int value)
{
return new Mutable(value);
}
}
The class is not final, subclassing should be safe.
All of the constructors must be private.
public accessors should be final.
private mutators in the base class should be final.
public mutators in the Mutable class should be final.
Use factory methods to construct immutable and mutable objects.
This is like the subclass mutable pattern, but since the Mutable class is an inner class, it has access to private fields and methods in the base class, so nothing needs to be protected which could possibly be overridden. The base class is just like a standard mutable class, except the constructors and mutators are private. The mutable subclass is a thin layer (every method is super...) that exposes the mutators.
To create an immutable instance: Bob test1 = Bob.immutable(99); To create a mutable instance: Bob.Mutable test2 = Bob.mutable();
Another possible solution is the State design pattern. Since it main concept is altering an object's behavior when its state changes. Also allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
In your case you can consider the following implementation:
//maintains an instance of a ConcreteState subclass that defines the current state
public class Holder {
//your code
}
//encapsulating the behavior associated with a particular state of the Holder
public abstract class State{
//your code
}
//implements a behavior associated with a state of Holder
public class MutableHolderState extends State {
//your code
}
//implements a behavior associated with a state of Holder
public class ImmutableHolderState extends State {
//your code
}

Why would one declare an immutable class final in Java?

I read that to make a class immutable in Java, we should do the following,
Do not provide any setters
Mark all fields as private
Make the class final
Why is step 3 required? Why should I mark the class final?
If you don't mark the class final, it might be possible for me to suddenly make your seemingly immutable class actually mutable. For example, consider this code:
public class Immutable {
private final int value;
public Immutable(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Now, suppose I do the following:
public class Mutable extends Immutable {
private int realValue;
public Mutable(int value) {
super(value);
realValue = value;
}
public int getValue() {
return realValue;
}
public void setValue(int newValue) {
realValue = newValue;
}
public static void main(String[] arg){
Mutable obj = new Mutable(4);
Immutable immObj = (Immutable)obj;
System.out.println(immObj.getValue());
obj.setValue(8);
System.out.println(immObj.getValue());
}
}
Notice that in my Mutable subclass, I've overridden the behavior of getValue to read a new, mutable field declared in my subclass. As a result, your class, which initially looks immutable, really isn't immutable. I can pass this Mutable object wherever an Immutable object is expected, which could do Very Bad Things to code assuming the object is truly immutable. Marking the base class final prevents this from happening.
Contrary to what many people believe, making an immutable class final is not required.
The standard argument for making immutable classes final is that if you don't do this, then subclasses can add mutability, thereby violating the contract of the superclass. Clients of the class will assume immutability, but will be surprised when something mutates out from under them.
If you take this argument to its logical extreme, then all methods should be made final, as otherwise a subclass could override a method in a way that doesn't conform to the contract of its superclass. It's interesting that most Java programmers see this as ridiculous, but are somehow okay with the idea that immutable classes should be final. I suspect that it has something to do with Java programmers in general not being entirely comfortable with the notion of immutability, and perhaps some sort of fuzzy thinking relating to the multiple meanings of the final keyword in Java.
Conforming to the contract of your superclass is not something that can or should always be enforced by the compiler. The compiler can enforce certain aspects of your contract (eg: a minimum set of methods and their type signatures) but there are many parts of typical contracts that cannot be enforced by the compiler.
Immutability is part of the contract of a class. It's a bit different from some of the things people are more used to, because it says what the class (and all subclasses) can't do, while I think most Java (and generally OOP) programmers tend to think about contracts as relating to what a class can do, not what it can't do.
Immutability also affects more than just a single method — it affects the entire instance — but this isn't really much different than the way equals and hashCode in Java work. Those two methods have a specific contract laid out in Object. This contract very carefully lays out things that these methods cannot do. This contract is made more specific in subclasses. It is very easy to override equals or hashCode in a way that violates the contract. In fact, if you override only one of these two methods without the other, chances are that you're violating the contract. So should equals and hashCode have been declared final in Object to avoid this? I think most would argue that they should not. Likewise, it is not necessary to make immutable classes final.
That said, most of your classes, immutable or not, probably should be final. See Effective Java Second Edition Item 17: "Design and document for inheritance or else prohibit it".
So a correct version of your step 3 would be: "Make the class final or, when designing for subclassing, clearly document that all subclasses must continue to be immutable."
Don't mark the entire class final.
There are valid reasons for allowing an immutable class to be extended as stated in some of the other answers so marking the class as final is not always a good idea.
It's better to mark your properties private and final and if you want to protect the "contract" mark your getters as final.
In this way you can allow the class to be extended (yes possibly even by a mutable class) however the immutable aspects of your class are protected. Properties are private and can't be accessed, getters for these properties are final and cannot be overridden.
Any other code that uses an instance of your immutable class will be able to rely on the immutable aspects of your class even if the sub class it is passed is mutable in other aspects. Of course, since it takes an instance of your class it wouldn't even know about these other aspects.
If you do not make it final I can extend it and make it non mutable.
public class Immutable {
privat final int val;
public Immutable(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
public class FakeImmutable extends Immutable {
privat int val2;
public FakeImmutable(int val) {
super(val);
}
public int getVal() {
return val2;
}
public void setVal(int val2) {
this.val2 = val2;
}
}
Now, I can pass FakeImmutable to any class that expects Immutable, and it will not behave as the expected contract.
If it's not final then anyone could extend the class and do whatever they like, like providing setters, shadowing your private variables, and basically making it mutable.
That constraints other classes extending your class.
final class can't be extended by other classes.
If a class extend the class you want to make as immutable, it may change the state of the class due to inheritance principles.
Just clarify "it may change". Subclass can override superclass behaviour like using method overriding (like templatetypedef/ Ted Hop answer)
For creating an immutable class it is not mandatory to mark the class as final.
Let me take one such example from the standard library itself: BigInteger is immutable but it's not final.
Actually, immutability is a concept according to which once an object is created, it can not be modified.
Let's think from the JVM point of view. From the JVM point of view, an object of this class should be fully constructed before any thread can access it and the state of the object shouldn't change after its construction.
Immutability means there is no way to change the state of the object once it is created and this is achieved by three thumb rules which make the compiler recognize that class is immutable and they are as follows:
All non-private fields should be final
Make sure that there is no method in the class that can change the fields of the object either directly or indirectly
Any object reference defined in the class can't be modified from outside of the class
For more information refer to this URL.
Let's say you have the following class:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class PaymentImmutable {
private final Long id;
private final List<String> details;
private final Date paymentDate;
private final String notes;
public PaymentImmutable (Long id, List<String> details, Date paymentDate, String notes) {
this.id = id;
this.notes = notes;
this.paymentDate = paymentDate == null ? null : new Date(paymentDate.getTime());
if (details != null) {
this.details = new ArrayList<String>();
for(String d : details) {
this.details.add(d);
}
} else {
this.details = null;
}
}
public Long getId() {
return this.id;
}
public List<String> getDetails() {
if(this.details != null) {
List<String> detailsForOutside = new ArrayList<String>();
for(String d: this.details) {
detailsForOutside.add(d);
}
return detailsForOutside;
} else {
return null;
}
}
}
Then you extend it and break its immutability.
public class PaymentChild extends PaymentImmutable {
private List<String> temp;
public PaymentChild(Long id, List<String> details, Date paymentDate, String notes) {
super(id, details, paymentDate, notes);
this.temp = details;
}
#Override
public List<String> getDetails() {
return temp;
}
}
Here we test it:
public class Demo {
public static void main(String[] args) {
List<String> details = new ArrayList<>();
details.add("a");
details.add("b");
PaymentImmutable immutableParent = new PaymentImmutable(1L, details, new Date(), "notes");
PaymentImmutable notImmutableChild = new PaymentChild(1L, details, new Date(), "notes");
details.add("some value");
System.out.println(immutableParent.getDetails());
System.out.println(notImmutableChild.getDetails());
}
}
Output result will be:
[a, b]
[a, b, some value]
As you can see while original class is keeping its immutability, child classes can be mutable. Consequently, in your design you cannot be sure that the object you are using is immutable, unless you make your class final.
Suppose the following class were not final:
public class Foo {
private int mThing;
public Foo(int thing) {
mThing = thing;
}
public int doSomething() { /* doesn't change mThing */ }
}
It's apparently immutable because even subclasses can't modify mThing. However, a subclass can be mutable:
public class Bar extends Foo {
private int mValue;
public Bar(int thing, int value) {
super(thing);
mValue = value;
}
public int getValue() { return mValue; }
public void setValue(int value) { mValue = value; }
}
Now an object that is assignable to a variable of type Foo is no longer guaranteed to be mmutable. This can cause problems with things like hashing, equality, concurrency, etc.
Design by itself has no value. Design is always used to achieve a goal. What is the goal here? Do we want to reduce the amount of surprises in the code? Do we want to prevent bugs? Are we blindly following rules?
Also, design always comes at a cost. Every design that deserves the name means you have a conflict of goals.
With that in mind, you need to find answers to these questions:
How many obvious bugs will this prevent?
How many subtle bugs will this prevent?
How often will this make other code more complex (= more error prone)?
Does this make testing easier or harder?
How good are the developers in your project? How much guidance with a sledge hammer do they need?
Say you have many junior developers in your team. They will desperately try any stupid thing just because they don't know good solutions for their problems, yet. Making the class final could prevent bugs (good) but could also make them come up with "clever" solutions like copying all these classes into a mutable ones everywhere in the code.
On the other hand, it will be very hard to make a class final after it's being used everywhere but it's easy to make a final class non-final later if you find out you need to extend it.
If you properly use interfaces, you can avoid the "I need to make this mutable" problem by always using the interface and then later adding a mutable implementation when the need arises.
Conclusion: There is no "best" solution for this answer. It depends on which price you're willing and which you have to pay.
The default meaning of equals() is the same as referential equality. For immutable data types, this is almost always wrong. So you have to override the equals() method, replacing it with your own implementation. link

Inheritance of final fields in Java?

What happens when a superclass has a field marked final, but a subclass overrides (hides?) this field? 'Final' doesn't stop this, does it?
The specific example I'm working on is a Building class, from which different kinds of buildings inherit. The cost of each type, among other things, should be final to each subclass, but each type of building should have their own cost.
Edit: I've since realized that I had no idea what I was talking about above. What I really want are static variables of cost. However, if I declare these static variables in the superclass, they are static to the superclass, so Subclass1.cost, e.g., refers to the same value as Superclass.cost or Subclass2.cost. How can I make variables that are static to each subclass, without having to declare them in each class.
The final keyword, when applied to fields of a Java class, has nothing to do with inheritance. Instead, it indicates that outside of the constructor, that field cannot be reassigned.
Java treats name hiding and overriding separately. Overriding actually changes the observable behavior of the program at runtime by switching which function is called, while name hiding changes the program by changing the static interpretation of which field is being reference. final as applied to overriding only works for methods, because fields in Java cannot be overridden. The use of final in these different contexts is a bit confusing, unfortunately, and there is no way to prevent a field from having its name hidden in a subclass.
If you want the buildings to have different costs, one option would be to have an overridden getCost method which is overridden differently in each derived class. Alternatively, you could have a single protected or private field in the base class that stores the cost, then have each subclass set this field either directly (if this is protected) or through a base class constructor (if this field is private).
Hope this helps!
You can do this two ways: make an accessor function and hide the field itself or else pass the building cost to the superclass constructor from the subclass. You can combine these and make a property that can't be overridden by subclasses:
public class Building {
private final int cost;
protected Building(int cost, ...) {
this.cost = cost;
}
public final int getCost() {
return cost;
}
}
public class Cottage extends Building {
public Cottage() {
super(COTTAGE_COST, ...);
}
}
Agree with other answers, but I think the following implementation is better in this case:
public abstract class Building {
private final int cost;
public Building(int cost) {
this.cost = cost;
}
public final int getCost() {
return cost;
}
}
class Skyscraper extends Building {
public Skyscraper() {
super(100500);
}
}
Of course the field could be made public, but that's the other story...

Categories

Resources