According to this: A Strategy for Defining Immutable Objects
One of the conditions for a class to be immutable, is making all its fields final and private.
Why final??? The other conditions aren't sufficient?
Without making the field final we can make an immutable class/object if other conditions are available.
But I think the final is useful while dealing with concurrency and synchronization.
Per the definition for an immutable object (courtesy of Wikipedia) "In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created."
Once an final object has been created it cannot be re-assigned. Without the final key work you could still change an object after it has been created.
See also
final object in java
Counter question "Why not final?".
final means for primitive types you'll not be able to change the value once assigned which is enough to make them Immmutable,
while for non-primitive types the reference can't be changed (1st step towards Immutability) once assigned and you need to do some more as mentioned in the link shared by you.
The key to the linked document is this quote
Not all classes documented as "immutable" follow these rules....However, such strategies require sophisticated analysis and are not for beginners.
This is a tutorial for beginners. It's easier to tell them "make everything private and final" then have to explain all the edge cases with how to properly handle mutable references and making sure not to let your references escape.
Related
In C/C++ we use static local variables for maintaining a method's state. But why it is not supported in Java?
Yes, I can use an static field for this purpose. But isn't it a bit weird to create a field for maintaining only one method's state?
You have found the only solution.
Java dropped a number of complexities from C++, and this was one of them.
Static variables scoped to a function do nasty things to you in concurrency (e.g. strtok is a famously nasty one to use with pthreads, for exactly this reason).
In general, what you want is an object with state. The function in question should then have an object-level variable. Then you can create instances that each maintain state.
Much easier to understand/maintain/etc.
If you truly need to maintain state as a singleton, then static fields are it.
The Java language spec doesn't seem to defend the omission of variables that correspond to C static variables.
Hiding state in class methods has a few drawbacks when seen from a Java perspective. Generally the existence of a function-level static variable isn't the sort of implementation detail that you'd want to expose outside of that function.
But the method's state is actually part of the class's state, and method-level static variables would have to be serialized / deserialized any time the object is persisted. This might not sound common, coming from a C background, so I'll note a few common examples.
Application server clusters can pass user session objects between nodes in order to provide fault tolerance.
JAXB could be used to marshall an object into an XML document
JPA can be used to persist object state to a database
If the variable's value is worth saving when the object is persisted, then there's a good chance that code outside of that class will need to reference that value. And suddenly that means defining access levels -- is a static variable in a public method automatically public? Or would a programmer have to declare it so?
We also have to think about extensibility. Would derived classes be required to implement the same static variable? Or would there be a reference to the variable from the function in the base class?
It's more likely that the C method that would use a static local variable would be a good candidate for a class in Java. It has state and hopefully exists for a single purpose. There's little drawback to encapsulating the functionality into an object, and it makes for a cleaner separation between transient values (such as local variables) and more long-term state.
Some of the other answers show why you might not want to have this. But you can also ask why from a historical perspective.
To answer this you have to start to see why C does have static local variables. C has much fewer means than Java and C++ to limit the scope of a variable, the only options for static data are 'inside the file' and 'everywhere'. So this provides an extra layer, to limit the scope.
An important aspect of C++ is compatibility with, so it is allowed in C++ as well. But it doesn't need local static scope as much anymore, because there are many other means to limit scope of static data. The use is not popular in (modern) C++.
Java merely takes a lot of inspiration from C/C++, it didn't have to worry about backwards compatibility, so it could be left out.
Perhaps because methods are not objects in Java; so maintaining their state as you said make not much sense and I guess you'd have to create a new concept in the byte code for that; use an object as Tony K. said.
instance methods are invoked by the instance(objects) of the class . Static things belongs to the class not to the object that's why local variables are not static.Instance variables are static and they can also initialized at the time of class loading by static blocks.
enter image description here
for more information please visit :- https://www.youtube.com/watch?v=GGay1K5-Kcs&t=119s
It is well-known that the type wrappers such as Integer, Double, Boolean are immutable. However, I was unable to find this documented in the official API documentation, e.g., https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html. I also looked in the source code files, and did not find this stated in the comments. (The comments in the source code for String, on the other hand, does mention its immutability.)
Is this because:
- it's documented elsewhere (if so, where?),
- this fact is too "well-known", or
- the developer is expected to read the implementation of the wrappers and figure out whether the wrapper is immutable or not?
It is worth consideration that immutable can mean two things:
a) that if you pass this value somwhere it can't be mutated.
b) "a" and that it can be safely used in multithreaded environment
ad A) There are classes that are just immutable but not thread safe, they are good to be used with setters/getters and to be keys in HashMap - these ones with no mutators, with all fields private but without all fields final or volatile.
ad B) There are classes that are immutable and thread safe - these without mutators and with all fields private and final or volatile.
Classes that are thread safe are often described as so in the documentation or even by name, of course some classes can be immutable and/or thread safe but not strictly documented as so. For example the String class is documented to be "constant", but there is no information about thread safety - there is only one enigmatic statement "Because String objects are immutable they can be shared" but I think it means something different than ...shared with other threads. We just know the properties of popular classes, but I agree that these properties should be clearly documented. Unfortunatelly in real life they aren't. So the only way to know if class is immutable is to check the documentation and if there is not enough information, then check the implemetation and ask the author if He plans to make the class mutable in the future. This topic is considered in a book Java Concurrency in Practice, and the author suggest to use two annotations to denote that something is #ThreadSafe and/or #Immutable but unfortunatelly this isn't a common practice yet.
The boxed wrappers are "immutable" because they're virtually
interchangeable syntactically with the literal types they wrap. For example boolean is immutable:
boolean x = false;
x.flip(); // not implemented
Native types in most programming languages are immutable. Therefore, by the wrapper contract,
Boolean x = false;
x.mutate(/* ??? */);
is not defined either.
i know the reason, why String is immutable but my question is why the concept of immutability
sticks to only String class in java , why it won't apply to others.
one of the reason i found why it is immutable is HERE
but why not all other classes like Integer and so on..
how java people decided changing their values might not effect ..
please explain .
The point is that you could confuse a String (which is an Object) with a primitive type. In fact, The way strings typically appear in Java programs can lead to confusion.
There are shortcuts available for strings that are not available for other objects in Java. These
shortcuts are highly used and they give strings the appearance of a primitive data type. But,
strings are objects and they possess all the attributes and behaviours of objects in Java
When designing a class, to make it immutable or not is a design choice and usually a tradeoff. The classes String and Integer were made immutable for many reasons including security.
A class like java.util.Random is all about managing some state, so it has to be mutable.
A class like java.awt.Rectangle is mutable, which has the advantage of saving memory management costs when you modify one rather than create a new one, but unfortunately it means that when a Rectangle instance that's shared (e.g. by two different window objects), changing it for one of them will change it out from under the others, causing unhappy surprises. Modern garbage collectors are very efficient [I hear they're more efficient than C's malloc() and free()] so mutability may not actually save memory management overhead, certainly not if you often have to copy objects to protect against accidental shared changes.
You can freely share an immutable object without worrying about it changing out from under you.
Integer is immutable, so each operation on it creates a new instance.
Immutable does not mean that a refernece can never assign another value. For example, String is immutable too, but we can do this:
String ex = "good"; // ex == "good"
ex = ex + "morning"; // now ex == "goodmorning"
So what happened there? Since String is immutable, clearly "ex" was not changed. But it now being assigned something different. This is because "ex" is now a completely newly instantiated object.
So this is same the case of Integer.
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.
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.
But even finalizers don't force an extra sweep. What happens is that an object that needs finalization is set on one side until the main GC finishes. The GC then runs the finalize method on the object and sets its flag ... and continues. The next time the GC runs, the object is treated as a normal object:
if it is reachable it is marked and copied
if it is not reachable it is not marked.
(Your characterization - "Java generational garbage collection mark-sweep" is garbled. A garbage collector can be either "mark-sweep" OR "generational" (a subclass of "copying"). It can't be both. Java normally uses generational collection, and only falls back to mark-sweep in emergencies; i.e. when running out of space or when a low pause collector cannot keep up.)
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. A modern JIT compiler does this optimization for non-final methods too, if they are not overridden by any class that the application actually uses. (Clever stuff happens ...)
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 to the first, a final field can't be switched from mutable to immutable.
It is unclear what you mean by the second part. It is true that you can use a factory (or builder) pattern to construct immutable objects. However, if you use final for the object fields at no point will the object be mutable.
Alternatively, you can implement immutable objects that use non-final fields to represent immutable state, and you can design the API so that you can "flip a switch" to make a previously mutable object immutable from now onwards. But if you take this approach, you need to be a lot more careful with synchronization ... if your objects need to be thread-safe.
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. And enums can be mutable.
Final keyword is usually used to preserve immutability. To use final for classes or methods is to prevent linkages between methods from being broken. For example, suppose the implementation of some method of class X assumes that method M will behave in a certain way. Declaring X or M as final will prevent derived classes from redefining M in such a way as to cause X to behave incorrectly.
Merely out of interrest: do you think Java would have been a better language if static variables would have been excluded, effectively replacing Singletons with singletons? Definition here.
If you think so: could you elaborate on what motivation there might have been for including it in the language?
The same article that you cite has the following statement:
The other kind of Singletons, which are semi-acceptable are those which don't effect the execution of your code, They have no "side effects"
... and then the article explains about logging. Another typical example is Printing. So that are arguments for Singletons even in the article that calls for "let's-get-rid-of-all-singletons".
The argument the author provides is interesting. He states that having global state is the real problem with Singletons, and as long as there is a one-way communication between your program and the Singleton you are in the clear.
And definitively Java would be a worse language if it had no static variables, as it is a feature that is required in several use cases. I mean, you could program in a procedural way in Java if you really wanted... and that is not evil per-se.
The abuse of static variables and Singletons doesn't necessarily mean that we need to get rid of them.
do you think Java would have been a better language if static variables would have been > excluded, effectively replacing Singletons with singletons?
No, sometimes you really want to have variables or constants that are common to all objects. Of course static is not necessary evil.
Could you elaborate on what motivation there might have been for including it in the
language?
static is a shorthand for objects or methods that are not necessary bounded to data, it models behaviour without instance data.
Clearly static constants are useful. To make an object constant in Java you define an immutable type. As it currently stands Java is a bit lacking in constant types. For instance, it is very common to see a static field with a (non-empty) array but (hopefully_ treated as a constant.
There are a relatively few cases where mutable statics make sense. Some caches and adding external fields to existing objects, for instance. Analogously, even the constant String has a mutable field.
So entirely getting rid of statics is a bit difficult for general purpose languages. Having siad that I believe Fan and Newspeak do that.
However, the common mutable static, whether dressed as a Singleton or not, is definitely something that could go. APIs would of course be different. It would make my job a lot easier. The SecurityManager mechanism would be redundant, for example.
Despite despising singletons and anything static nonfinal, I do occasionally use the following idiom to generate unique IDs for objects.
private static long idCounter;
private synchronized static long getID() { return idCounter++; }
private final long id = getID();
So that's one argument for having static nonfinals.
(Or, as Tom Hawtin points out, the slightly better
private static final AtomicLong idCounter = new AtomicLong();
private final long id = idCounter.getAndIncrement();
)
I think java would be a prettier language without static, but I don't think it follows that the Singleton anti-pattern would be cured by removing the keyword.
A singleton is evil because it 'knows' something about itself that it shouldn't, namely that it is the only instance of its type in the whole system. Any time this sort of information is encapsulated in a class you have a defacto Singleton.
As to why it's in Java, I would speculate that, like a whole range of things, it is a compromise between OO purity and practicality.
I agree with DFA. Sometimes Static makes sense.
Also it is a language feature someone who despises it can choose not to use it. I find statics and Singletons useful.