making a class immutable in java

2019-02-21 22:56发布

To make a class immutable what I can do is:

1)Make class final
2)do not provide setters
3)mark all variables as final

But if my class has another object of some other class then , somone can change value of that object

class MyClass{
 final int a;
 final OtherClass other 

 MyClass(int a ,OtherClass other){
  this.a = a;
  this.other = other;
 }

 int getA(){
   return a;
 }

 OtherClass getOther(){
   return other;
 }

 public static void main(String ags[]){
  MyClass m = new Myclass(1,new OtherClass);
  Other o = m.getOther();
  o.setSomething(xyz) ; //This is the problem ,How to prevent this?

}
}

8条回答
smile是对你的礼貌
2楼-- · 2019-02-21 23:46

A) Make the OtherClass immutable as well

or

B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.

Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.

查看更多
一夜七次
3楼-- · 2019-02-21 23:47

But If my class has another object of some other class then , somone can change value of that object...

Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.

One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.

查看更多
混吃等死
4楼-- · 2019-02-21 23:48

I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.

If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.

查看更多
倾城 Initia
5楼-- · 2019-02-21 23:48

Return deep clones from your getters. You may find this to be no easy task.

查看更多
老娘就宠你
6楼-- · 2019-02-21 23:49

It is possible to create the immutable class in java by following ways

1.Don't Provide setter methods.

2.Make all fields are as final and private.

3.Make Class as final.

查看更多
Luminary・发光体
7楼-- · 2019-02-21 23:50

Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:

  1. No way for an external user to change the value of the object
  2. A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result

Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).

So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:

  • Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
  • Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
  • Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.

All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)

查看更多
登录 后发表回答