Immutable Type: public final fields vs. getter

ε祈祈猫儿з 提交于 2019-11-27 03:53:00

I would do what you believe is simplest and clearest. If you have a data value class which is only used by a restricted number of classes. esp a package local class. then I would avoid getter/setters and use package local or public fields.

If you have a class which you expect other modules/developers to use, following a getter/setter model may be a safer approach in the long run.

The problem is the uniform access principle. You may later need to modify foo so that it's obtained through a method instead of being fixed, and if you exposed the field instead of a getter, you'll need to break your API.

This answer is obviated:

Why not

interface Immu { String getA() ; String getB ( ) }

Immu immu ( final String a , final String b )
{
       /* validation of a and b */
       return new Immu ( )
       {
              public String getA ( ) { return a ; }

              public String getB ( ) { return b ; }
       }
}

I use the public-final-field (anti?)pattern on home projects for classes which are basically an immutable data structure with a constructor, along with absolute basics like equals(), hashCode(), toString(), etc. if required. (I'm avoiding the word "struct" because of the various different language interpretations of it.)

I wouldn't bring this approach to someone else's codebase (work, public project, etc) because it would likely be inconsistent with other code, and principles like When In Rome or Least Surprise take priority.

That said, with regard to Daniel C. Sobral's and aioobe's answers, my attitude is that if the class design becomes a problem because of unforeseen developments, it's the work of 30 seconds in an IDE to privatise the fields and add accessors, and no more than 5 or 10 minutes to fix broken references unless there are hundreds of them. Anything that fails as a result gets the unit test it should have had in the first place.:-)

[Edit: Effective Java is quite firmly against the idea, while noting that it's "less harmful" on immutable fields.]

I found this thread hoping for some actual arguments, but the answers I've seen here didn't help me all that much. After some more research and thinking I think the following has to be considered:

  • public final looks cleanest for immutable types.
  • Mutable types could be altered by accessors even if this is not intended - in concurrent environments this could lead to a lot of headaches.
  • There can be no no-arguments constructor. This is importent if you need factory methods (e.g. for LMAX Disruptor). In a similar way instantiating your objects via reflection becomes more complicated.
  • Getters and setters can have side effects. Using public final clearly tells the programmer that no hidden magic is occuring and the object is inherently dumb :)
  • You can't return a wrapper or a derived class instance to the accessor. Then again, this is something you should know about when the field is assigned its value. In my opinion container classes should not be concerned about what to return to whom.

If you're mid development and no guideline is stopping you and the project is isolated or you have control over all involved projects I'd suggest using public final for immutable types. If you decide you need getters later on, Eclipse offers Refactor -> Encapsulate Field... which automatically creates these and adjusts all references to the field.

It is not very clear if someone is going to use your code through an API. You are also missing an opportunity to validate the input, if you are going to require some later.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!