tags:

views:

198

answers:

2

I was told that, I misunderstand effects of final. What are the effects of final keyword?

Here is short overview of what I think, I know:

Java final modifier (aka aggregation relation)

primitive variables: can be set only once. (memory and performance gain)
objects variables: may be modified, final applies to object reference.
fields: can be set only once.
methods: can't be overridden, hidden.
classes: can't be extended.
garbage collection: will force Java generational garbage collection mark-sweep to double sweep.

Can's and Cant's

  • Can make clone fail (this is both good and bad)
  • Can make immutable primitives aka const
  • Can make blank immutable - initialized at creation aka readonly
  • Can make objects shallowly immutable
  • Can make scope / visibility immutable
  • Can make method invocation overhead smaller (because it does not need virtual table)
  • Can make method arguments used as final (even if thy are not)
  • Can make objects threadsafe (if object is defined as final, it wont make method arguments final)
  • Can make mock tests (not that you could do anything about it - you can say bugs are intended)
  • Can't make friends (mutable with other friends and immutable for rest)
  • Can't make mutable that is changed to be immutable later (but can with factory pattern like fix)
  • Can't make array elements immutable aka deeply immutable
  • Can't make new instances of object (this is both good and bad)
  • Can't make serialization work

There are no alternatives to final, but there is wrapper + private and enums.

A: 

I think you have any exhaustive list out there. Pretty much you covered everything

kuriouscoder
+14  A: 

Answering each of your points in turn:

primitive variables: can be set only once. (memory and performance gain)

Yes, but no memory gain, and no performance gain. (Your supposed performance gain comes from setting only once ... not from final.)

objects variables: may be modified, final applies to object reference.

Yes. (However, this description miss the point that this is entirely consistent with the way that the rest of the Java language deals with the object / reference duality. For instance, when objects are passed as parameters and returned as results.)

fields: can be set only once.

The real answer is: same as for variables.

methods: can't be overridden, hidden.

Yes. But also note that what is going on here is that the final keyword is being used in a different syntactic context to mean something different to final for an field / variable.

classes: can't be extended.

Yes. But also see note above.

garbage collection: will force Java generational garbage collection mark-sweep to double sweep.

This is nonsense. The final keyword has no relevance whatsoever to garbage collection. (You might be confusing final with finalization ... they are unrelated.)

Can make clone fail (this is both good and bad)

I don't think so.

Can make immutable primitives aka const

Yes.

Can make blank immutable - initialized at creation aka readonly

Yes ... though I've never heard the term "blank immutable" used before.

Can make objects shallowly immutable

Object mutability is about whether observable state may change. As such, declaring attributes final may or may not make the object behave as immutable. Besides the notion of "shallowly immutable" is not well defined, not least because the notion of what "shallow" is cannot be mapped without deep knowledge of the class semantics.

(To be clear, the mutability of variables / fields is a well defined concept in the context of the JLS. It is just the concept of mutability of objects that is undefined from the perspective of the JLS.)

Can make scope / visibility immutable

Terminology error. Mutability is about object state. Visibility and scope are not.

Can make method invocation overhead smaller (because it does not need virtual table)

In practice, this is irrelevant. The JIT compiler does this optimization for non-final methods too if they are not overridden.

Can make method arguments used as final (even if thy are not)

Huh? I cannot parse this sentence.

Can make objects threadsafe

In certain situations yes.

(if object is defined as final, it wont make method arguments final)

Yes, if you mean if class is final. Objects are not final.

Can make mock tests (not that you could do anything about it - you can say bugs are intended)

Doesn't parse.

Can't make friends (mutable with other friends and immutable for rest)

Java doesn't have "friends".

Can't make mutable that is changed to be immutable later (but can with factory pattern like fix)

Yes, and No.

Can't make array elements immutable aka deeply immutable

Yes, but your terminology is broken; see comment above about "shallow mutability".

Can't make new instances of object (this is both good and bad)

No. There's nothing stopping you making a new instance of an object with final fields or a final class or final methods.

Can't make serialization work

No. Serialization works. (Granted, deserialization of final fields using a custom readObject method presents problems ... though you can work around them using reflection hacks.)

There are no alternatives to final,

Correct.

but there is wrapper + private

Yes, modulo that (strictly speaking) an unsynchronized getter for a non-final field may be non-thread-safe ... even if it is initialized during object construction and then never changed!

and enums.

Solves a different problem.

Stephen C
Well, Java does have friends (quite a lot, in fact). It just does not have friends in the sense that C++ uses them ;-).
sleske
If by "Can make clone fail" he means, "Can make a deep clone difficult to impossible to implement" then that is true. Also, final can make custom serialization hard, although basic serialization works.
ILMTitan
the mutability of visible variables is used for anonymous classes. Only immutable (final) local variables are visible to an anonymous class. So the terminology could work.
josefx
@josefx - it is the notion of "deep mutability" that is broken. Mutability *per se* makes sense, provided that you don't talk about mutability of variables and mutability of objects in the same breath.
Stephen C
@ILMTitan - 1) The standard clone contract says that it is shallow. 2) deep clone should always be possible, assuming that you are free to implement your own private constructor in the class you are implementing `clone`. 3) Java clone, and especially deep clone is conceptually flawed, and experienced developers should avoid it. If you need copying, implement using a copy constructor or final methods, and with well-defined *application specific* semantics.
Stephen C
@Stephen C - 1) Object.clone() creates a shallow copy, but the Javadoc says it should be overridden to perform a deep one (It uses the phrase "Independent"). 2) The standard convention for clone is to operate on a copy returned by super.clone(). That way, the copy will always be of the correct type even when a subtype does not override clone. Don't use constructors in clone. 3) Agreed.
ILMTitan