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
Related
Consider the following code:
public interface MyClass {
public final String getMyObject1();
public final String getMyObject2();
}
public class MyClass1 implements MyClass {
private String myObject1;
private String myObject2;
public MyClass1(String myObject1, String myObject2) {
this.myObject1 = myObject1;
this.myObject2 = myObject2;
}
public String getMyObject1() {
return myObject1;
}
public String getMyObject2() {
return myObject2;
}
}
public interface MyClass2 extends MyClass {
public static MyClass2 newInstance(String myObject1, String myObject2) {
return new MyClass2() {
public String getMyObject1() {
return myObject1;
}
public String getMyObject2() {
return myObject2;
}
};
}
}
And I use them like
public static void func(MyClass m) {
m.getMyObject1();
m.getMyObject2();
}
func(new MyClass1(o1, o2));
func(MyClass2.newInstance(o1, o2));
I wonder how they differ and if I only need to read from the values (i.e. to use MyClass as a "struct" to pass values), using the anonymous class can it be a simpler approach?
Otherwise, what are the draw backs?
One core rule of programming: try to not surprise your readers.
Your approach here to use a static class within an interface as "factory" method is very surprising (and believe me: I have seen a lot of Java code).
If at all, the more "common" way of handling such things: create a static class with a slightly similar name, you know, like there is java.lang.Object and java.lang.Objects that carries some useful static helper methods.
And beyond that, there is already a class in Java that helps with arbitrary numbers of "named" values; and that is called a Map!
Finally: there are some good arguments for "DTO"s (data transfer objects) but esp. for "beginners", you should rather look into "real" OO designs; based on the SOLID principles. In that sense: design real classes that exactly model your problem domain; and that provide helpful abstractions. A struct with an arbitrary number of members ... doesn't fall into either category.
The problem here is not the code necessarily but the design. I would be interested to know the real world use case you are trying to design here.
Surely there are limitations in the second approach like you cannot update the value of your objects at all once your class is created as you just have a way to get the value of the passed objects back.
Coming back to Design:
An interface is supposed to be an action which your class can perform if it implements that interface. In your case you are trying to return the value of two instance variables using the two methods in your interface which is a kind of action but it ignores the basic principle of encapsulation.
If your class defines/owns those instance variables it should have the getters and setters for that. You should not require an interface to do that. So ideally your interface should not be required. Any other class which uses MyClass1 object should directly use the getters and setters of the MyClass1.
"Return an immutable interface to the original data. You can then change fields in the object, but the caller cannot unless he cheats by casting. You expose only the methods you want the user to have. Doing the same with classes is trickier since a subclass must expose everything its superclass does"
What does he mean you can cheat, and why is it tricky with subclasses ?
source: http://mindprod.com/jgloss/immutable.html
You provide an interface that has no mutation methods. Then, you provide mutable implementations that are only known to the creator.
public interface Person
{
String getName();
}
public class MutablePerson implements Person
{
private String name;
public MutablePerson(String name)
{
this.name = name;
}
#Override
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
At this point, if you return Person objects everywhere, the only way for someone to modify the returned object is to cheat and cast it back to a MutablePerson. In effect, the mutable objects become immutable unless the code is a complete hack.
Person person = new MutablePerson("picky");
// someone is cheating:
MutablePerson mutableAgain = (MutablePerson)person;
mutableAgain.setName("Phoenix");
// person.getName().equals("Phoenix") == true
When not dealing with a bunch of younger programmers that will notice the true implementation is mutable, and thus they can cast it to change it, then you provide the safety of immutability with the benefit of being able to put it together without an endless constructor, or using a Builder (in effect, the mutable version is the Builder). A good way to avoid developers abusing the mutable version is to leave the mutable version as package private so that only the package knows about it. The negative of that idea is that this only works if it will be instantiated in the same package, which may be the case, but it obviously may not be the case in situations such as where DAO's are used with multiple package-defined implementations (e.g., MySQL, Oracle, Hibernate, Cassandra, etc., all returning the same stuff, and hopefully separated from each other to avoid cluttering their packages).
The real key here is that people should never build up from the Mutable objects except to implement further-down interfaces. If you're extending, and then returning an immutable subclass, then it's not immutable if it exposes a mutable object, by definition. For example:
public interface MyType<T>
{
T getSomething();
}
public class MyTypeImpl<T> implements MyType<T>
{
private T something;
public MyTypeImpl(T something)
{
this.something = something;
}
#Override
public T getSomething()
{
return something;
}
public void setSomething(T something)
{
this.something = something;
}
}
public interface MyExtendedType<T> extends MyType<T>
{
T getMore();
}
public class MyExtendedTypeImpl<T>
extends MyTypeImpl<T>
implements MyExtendedType<T>
{
private T more;
public MyExtendedTypeImpl(T something, T more)
{
super(something);
this.more = more;
}
#Override
public T getMore()
{
return more;
}
public void setMore(T more)
{
this.more = more;
}
}
This is honestly the way that Collections in Java should have been implemented. A readonly interface could have taken the place of the Collections.unmodifiable implementations, thus not having people unexpectedly using immutable versions of mutable objects. In other words, you should never hide immutability, but you can hide mutability.
Then, they could sprinkle immutable instances that truly can't be modified, and that would keep developers honest. Similarly, I would likely expect to see an immutable version of the above interface somewhere (with better names):
public class MyTypeImmutable<T> implements MyType<T>
{
private final T something;
public MyTypeImmutable(T something)
{
this.something = something;
}
#Override
public T getSomething()
{
return something;
}
}
I think that statement is not well worded, and he's touching on more than just immutability (and in fact, what that statement is not even really immutability).
The idea is that if you return an interface to the data, and not the specific class, the caller should only perform the actions on the interface. So if your interface only has getter methods, then there should be no way to manipulate the data (without downcasting).
Consider this hierarchy
interface AnInterface {
void aGetter();
}
class MyMutableClass {
void aGetter();
void aSetter(...);
}
Even though MyMutableClass is mutable, by returning AnInterface, the user doesn't know it's actually a mutable object. So the object isn't actually mutable, but you would have to downcast (or use reflection to access the mutator methods) to know that.
Now let's say you had
class MyImmutableSubclass extends MyMutableClass {
void anotherGetter();
}
Even though the subclass is "immutable" (which it's not really since its parent class is not immutable), if you return MyImmutableSubclass from the method, the caller can still call aSetter since MyMutableClass exposes it.
In general, using immutable objects is recommended to avoid "leaking" state. Anything that is truly immutable is safe from any manipulation and unintended changes.
You can cheat because you can change the type of the returned fields if you typecast to "something" mutable. If you "hide" your class behind a public interface and return that immutable interface, the user can cheat by typecasting your interface to your class.
With subclasses is trickier because any private members of a class are not inherited by the subclass but protected and public are. That means anything that you can access in your parent class from the outside can be accessed in the children from the outside too, so you can't really obfuscate the user as easily as you would with an interface. This is actually possible, i think, since you can override the parent methods, although I don't see much point in it.
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
I have a series of classes, A,B,C... (several dozen in total) that share common code. There can be many instance of each class A,B,C... . I'm planning to create a superclass, Abstract, that will contain that code instead.
Problem is, the common stuff works on an object that is unique on a per-class (not per-instance) basis. This is currently solved by A,B,C... each having a static field with the corresponding value. Obviously, when I refactor the functionality into Abstract, this needs to be changed into something else.
In practice, it currently looks like this (note that the actual type is not String, this is just for demonstrative purposes) :
public class A implements CommonInterface {
private static final String specificVar = "A";
#Override
public void common() {
specificVar.contains('');
}
}
public class B implements CommonInterface {
private static final String specificVar = "B";
#Override
public void common() {
specificVar.contains('');
}
}
The best idea I've come up with until now is to have a Map<Class<? extends Abstract>,K> (where K is the relevant type) static field in Abstract, and A,B,C... each containing a static initalization block that places the relevant value into the map. However, I'm not convinced this is the best that can be done.
Note that I'm not using any DI framework.
So, what would be the most concise, in terms of code contained in the subclasses, way to refactor the static fields in A,B,C... handled by the common code, without sacrificing field access efficiency?
Perhaps an enum is what you want.
enum MyInstances implements MyInterface {
A {
fields and methods for A
}, B {
fields and methods for B
};
common fields for all MyInstances
common methods for all MyInstances
}
// To lookup an instance
MyInstances mi = MyInstances.valueOf("A");
As you haven't shown any source code, we can't really tell if the use of static fields is a good or a bad design choice.
Considering the use of static fields by the subclasses is indeed a good design choice, the first way of having common code in a superclass to access them is by calling abstract methods that would be implemented in the subclasses.
Example:
public abstract class SuperClass {
public void processCommonLogic() {
// Common logic
// Execute specific logic in subclasses
processSpecificLogic();
}
public abstract void processCommonLogic();
}
public class ASubClass extends SuperClass {
public static int SPECIFIC_SUBCLASS_CONSTANT = 0;
public void processSpecificLogic() {
// Specific subclass logic
doSomethingWith(ASubClass.SPECIFIC_SUBCLASS_CONSTANT);
}
}
You could use the Template Method Pattern.
Have an abstract method getValue() defined in your abstract class and used within your abstract class wherever you require the value. Then each of your subclasses simply need to implement the getValue method and return the correct value for that subclass.
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;
}
}