Yes, and if you build a fire under a refrigerator, you can use it to heat food!
The statement that instances of a Java class are immutable does not mean that under no circumstances will the bits change. Besides using reflection, it would be easy enough to use JNI (native methods) to do the same thing. Both of these things are outside of the Java language proper and don't "count" in that statement.
More importantly, the promise of immutability is often used as a basis for making security-related assumptions. Note that both changing a private member via reflection, and loading an unknown native library, can be -- and generally are -- prohibited when a SecurityManager is in place. Environments that run untrusted code -- applet containers, RMI code when the classes are remotely downloaded -- always use a SecurityManager which makes all of this impossible, and ensures that String truly is immutable.
Essentially, "immutable" in Java always means unchangeable unless you use reflection (and unless reflection is allowed the necessary access by the security manager). This isn't an issue specific to Strings; it's true for all reference types in Java. [ November 17, 2005: Message edited by: Jim Yingst ]
Yes, and if you build a fire under a refrigerator, you can use it to heat food!
Wagner Danda Da Silva Filho
Ranch Hand
Joined: Mar 21, 2003
Posts: 80
posted
0
Originally posted by Ernest Friedman-Hill: Yes, and if you build a fire under a refrigerator, you can use it to heat food!
lol, excellent point of view!
SCJP, SCWCD
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
The important point is that the definition of "immutable" it loosely stated. According to the definition that Sun is assuming (and therefore, the intended audience of its documents), the statement holds true. Likewise, the fridge and fire analogy falls apart when some other context is applied as demonstrated.
In both cases, both contexts are extreme in practice, and so become negligible when making statements in documentation. You don't go to your whitegoods retailer and buy a fridge to warm your food up, simply because it can (under extreme conditions), do you?
Its a good thing Strings are immutable, I used to get headaches doing String manipulation from arrays in C/C++. You never want to use a refrigerator other than to keep your food cold, and you'd be best to ignore any crazy neighbors who might enjoy lighting them on fire, no matter how persuasive they are.
The reason why its told that string is immutable is because the String class is final.That means once we create a String object then we cant change it.When we try to append something to it.aCTUALLY A new string is created and the reference points there.So your original string remains the same thats its immutable
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
A final class does not imply immutable, merely, that the class is designed more appropriately than otherwise. In fact, a class is never immutable; it's interface is, and even then, what is "immutable"? I define it as have pre/post conditions on the contractual operations; that is, given the mutating operation X, the mutated behaviour can be observed through operation Y, which clearly, has nothing to do with classes.
For the case of java.lang.String, the "interface" and the "class" are (unfortunately) one and the same. Sun have made a somewhat lame attempt at extracting operations to an interface with CharSequence, but the distinction is still lacking heavily.
The actual object lc refers is not changed in the above code. toUpperCase creates a new String and give it's reference to uc. The api should have specified "Returns a new String with the characters in this String converted to upper case using the rules of the given Locale." instead of "Converts all of the characters in this String to upper case using the rules of the given Locale."
From Mutant
value is a field in String "private char value[];". Using reflection this Array is being replaced with the "orig.toUpperCase().toCharArray()"
The point here is Reflection can be used to break a limited set of contracts. Note that the 'private' access modifier for variable 'value' is not considered.
if you build a fire under a refrigerator, you can use it to heat food
is exactly what happens.
Renu Radhika
Ranch Hand
Joined: Oct 21, 2005
Posts: 243
posted
0
Thats what I meant.If you want to change the behaviour of a particular class we have to subclass it.But String class is final so we cant subclass it.Also in the API provided by sun its clearly mentioned that Strings are constants.So may be the private variable which holds the String value will be a final variable which cant be changed.
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
Originally posted by Renu Radhika: Thats what I meant.If you want to change the behaviour of a particular class we have to subclass it.But String class is final so we cant subclass it.Also in the API provided by sun its clearly mentioned that Strings are constants.So may be the private variable which holds the String value will be a final variable which cant be changed.
Changing the behaviour of a class has nothing to do with mutability. It is not clearly mentioned that Strings are constants, primarily, because they are not (unless the instance fits the criteria for one of course JLS 15.28). The private field of java.lang.String is final on most implementations, but final fields are changeable through reflection since 1.5 (for fun: why?). Nevertheless, that type is usually an array, which is (intrinsically as per array semantics) mutable, therefore, 'finality' is entirely irrelevant - one may mutate the array.
Changing the behaviour of a class has nothing to do with mutability.
That's not completely true. A class must be declared final to be (strongly) immutable. That is, class finality is a necessary though not sufficient condition of immutability. If you could subclass String, then you could change the bahavior of a method, say toString(), so that the String would seem mutable. Through polymorphism, the user of your String subclass might think he was just using a normal String, but could possibly see it demonstrating mutable characteristics.
A weakly immutable class would just declare certain methods to be final, and those would be the only ones guaranteed to be immutable.
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
Originally posted by Greg Charles:
That's not completely true. A class must be declared final to be (strongly) immutable. That is, class finality is a necessary though not sufficient condition of immutability. If you could subclass String, then you could change the bahavior of a method, say toString(), so that the String would seem mutable. Through polymorphism, the user of your String subclass might think he was just using a normal String, but could possibly see it demonstrating mutable characteristics.
A weakly immutable class would just declare certain methods to be final, and those would be the only ones guaranteed to be immutable.
It's entirely true under the provided context - that immutable classes cannot exist, merely, their contractual obligations. The ability to subtype classes is a consequence of a language defect, existing independantly from the notion of mutable/immutable contractual obligations.
The ability to subtype classes is a language defect? I'm not following your logic there. Be that as it may, Java and all languages that permit inheritence suffer this defect. Therefore immutable classes should be final.
Make a class immutable by following these guidelines :
always construct an object completely, instead of using a no-argument constructor combined with subsequent calls to setXXX methods
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
ensure no methods can be overridden - make the class final, or use static factories and keep constructors private
make fields final
if the state of a mutable object field is "owned" by the native class, and the intention is to allow direct access to the field only from within that native class, then, when the field "crosses the interface" (as in a get or set method, or in the constructor itself), then a defensive copy must be made, in order to maintain encapsulation.
if the state of a mutable object field is not "owned" by the native class, then a defensive copy of the object field is not necessary
jiju ka
Ranch Hand
Joined: Oct 12, 2004
Posts: 302
posted
0
The ability to subtype classes is a consequence of a language defect
Can somebody explain the logic behind this statement.
I believe the contrary is true. Inheritance is prevented by declaring a class as final. In the nature (real world objects) inheritance is not prohibited. [ November 30, 2005: Message edited by: jiju ka ]
Ken Blair
Ranch Hand
Joined: Jul 15, 2003
Posts: 1078
posted
0
Originally posted by jiju ka:
Can somebody explain the logic behind this statement.
I believe the contrary is true. Inheritance is prevented by declaring a class as final. In the nature (real world objects) inheritance is not prohibited.
[ November 30, 2005: Message edited by: jiju ka ]
I believe he was suggesting that being able to extend a class is a language defect. Yes, inheritance is prevented by declaring a class as final. You call that the contrary, but it is not contrary, it is irrelevent. What is a "real world object" anyway? If it's anything I've coded it's final and inheritance is prohibited, there's only one time I've ever used concrete inheritance.
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
Originally posted by Greg Charles: The ability to subtype classes is a language defect? I'm not following your logic there. Be that as it may, Java and all languages that permit inheritence suffer this defect. Therefore immutable classes should be final.
Yes, concrete inheritance (and interface inheritance as we currently know it) is a language defect, and can be traced to an implicit requirement defect under formal analysis given a set of axioms (one of which, for example, is that time is linear, therefore, the assertion may well fall apart at the relative speed of light). Complete reasoning omitted for brevity, and for now; let's assume it anyway.
In any case, to suggest that a *class* could be immutable is in fact, erroneous, despite what the literature tells you. Immutability is ill-defined, so I'll make a brave attempt - you might agree or not - an immutable type is one where a contractual operation is exposed that when invoked causes some other observable side effect on some other contractual operation. Here's an example: interface I{void setX(int x);int getX();} ...along with the English specification that given x and invocation of operations, setX(x), followed by getX(), the return value must be x. An unfortunate side-effect (there are many) is that by declaring a class non-final, you expose contract to clients in the future (assuming linear time).
It's also implied that a contractual mandate cannot be changed through "subtyping" (as we know it). That is given type T with a contractual obligation to remain immutable, subtype S will not (and cannot) change its contractual obligation (minor assumptions withstanding), however, it can itself expose operations which cause mutation. Therefore, since "S is a T" (excuse me while I puke), and "T must be immutable", then S must be immutable, and since time is linear, you cannot mandate that on the infinite possible subtypes of T. I find this reasoning (make no mistake, I do in fact understand the orthodox reasoning thoroughly) to be so loose, that it falls apart under stringent analysis. There are many examples of this occurring already in "more obvious" areas of software design. I (or someone at least for benefit of majority) hope to bring this one to the fore some day.
Jim Yingst
Wanderer
Sheriff
Joined: Jan 30, 2000
Posts: 18670
posted
0
[Tony]: ...(one of which, for example, is that time is linear, therefore, the assertion may well fall apart at the relative speed of light).
Commander, we're entering a region of space with an unusually high bogon flux. Raising shields...
[Tony]: an immutable type is one where a contractual operation is exposed that when invoked causes some other observable side effect on some other contractual operation.
Sounds like you just defined a mutable type. Though you refer to immutability several times later too, so I'm really not sure what the intent here was.
[Tony]: I find this reasoning (make no mistake, I do in fact understand the orthodox reasoning thoroughly) to be so loose, that it falls apart under stringent analysis.
OK. Were you going to provide some reasoning that doesn't fall apart? The thread of what you were saying has gotten quite murky by this point...
Going back:
[Tony]: immutable classes cannot exist
Are you saying that Strings don't exist? Strings aren't classes? Strings aren't immutable? The last seems most likely, though we've already addressed this earlier in the thread. Would you also argue that refrigerators don't exist?
Tony Morris
Ranch Hand
Joined: Sep 24, 2003
Posts: 1608
posted
0
Originally posted by Jim Yingst: [Tony]: ...(one of which, for example, is that time is linear, therefore, the assertion may well fall apart at the relative speed of light).
Commander, we're entering a region of space with an unusually high bogon flux. Raising shields...
Typical sarcasm and failure to acknowledge a relatively sound approach to reasoning. /ignore
[Tony]: an immutable type is one where a contractual operation is exposed that when invoked causes some other observable side effect on some other contractual operation.
Sounds like you just defined a mutable type. Though you refer to immutability several times later too, so I'm really not sure what the intent here was.
Oops - I meant to add a "not" in there somewhere.
[Tony]: I find this reasoning (make no mistake, I do in fact understand the orthodox reasoning thoroughly) to be so loose, that it falls apart under stringent analysis.
OK. Were you going to provide some reasoning that doesn't fall apart? The thread of what you were saying has gotten quite murky by this point...
Agreed, no less murky than the quoted literature. I reserve the right not to, just like you do.
Going back:
[Tony]: immutable classes cannot exist
Are you saying that Strings don't exist? Strings aren't classes? Strings aren't immutable? The last seems most likely, though we've already addressed this earlier in the thread. Would you also argue that refrigerators don't exist?
Correct, an immutable String does not exist. An immutable String contract does, however. Are you able to invoke an operation on a String instance that can be observed through some other operation? I'll bet not. The separation of contract (interface/API) from implementation (class) is the fundamental point. It is the contract that defines immutability (it's not obvious yet?). Hidden implementation details cannot be observed by clients, so why should they contribute to "immutability" details? Trivial, yet so widely misunderstood.
jiju ka
Ranch Hand
Joined: Oct 12, 2004
Posts: 302
posted
0
I have created another thread to discuss "language defect while subclassing".
Correct, an immutable String does not exist. An immutable String contract does, however. Are you able to invoke an operation on a String instance that can be observed through some other operation?
I will agree with Tony on this. Java language by itself is not imposing the immutability. In java Immutability is attained indirectly by relying on other contracts.
If java language is imposing immutability, there should be a "direct contract" with language. That contract in simple form may appear similar to "final" modifier.
Instead of having "String" declared as public final String,
Sun could have introduced another modifier called 'immutable' and used it as
public immutable String
Compiler will impose "no subclassing" and "no access setters" so that state of the String cannot be changed once it is created.