I want to ask how does the "".value transform char array,Thanks
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/**
* Initializes a newly created {#code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = "".value;
}
You should tell, which JRE implementation you are looking at, when you cite its source code.
However, the code is quite simple:
"" refers to a String constant which is initialized by the JVM
since you are inside the String() constructor which may get called by application code, but not JVM internal initialization, it may safely refer to the "" constant
like any other String object, it has the value field, so inside the String constructor, it is no problem to access that private field and copy the reference; it is equivalent to
String tmp = "";
this.value = tmp.value;
Since both, the "" constant and the instance created with the String() constructor represent empty strings, there is no problem in sharing the char[] array instance between them. However, there are reasons against it:
it is optimizing an uncommon case, as there is usually no reason to ever use the String() constructor at all
it is fragile as it relies on a particular JVM behavior, i.e. that the constant "" is not constructed via the String() constructor; if that assumption is wrong, this implementation will create a circular dependency
"".value
creates empty char[] array, equivalent of this.value = new char[0];
Related
I have been going through String class in Java in depth.
String in Java is backed by character array.
To create strings that have initial values, we call the constructor as:
/* String creation */
String s = new String("example");
The constructor code in the String class is:
public String(String original) {
this.value = original.value;
}
Can some one please explain me the logic of "original.value". From the source code, I understand it returns character array. But how java generates it?
The "foo" syntax has already constructed a String instance, it's syntactic sugar so that you don't have to write:
String foo = new String(new char[]{'f', 'o', 'o'});
So by the time you call new String("foo") you've already constructed a string once, and are now creating a copy of the first string - not "creat[ing] strings that have initial values".
Effective Java: Item 5 discusses this in more detail, and discourages ever using the new String(String) constructor.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
I do not understand why System.out.println(name) outputs Sam without being affected by the method's concat function, while System.out.println(names) outputs Sam4 as a result of the method's append method. Why is StringBuilder affected and not String? Normally, calling methods on a reference to an object affects the caller, so I do not understand why the String result remains unchanged. Thanks in advance
public static String speak(String name) {
name = name.concat("4");
return name;
}
public static StringBuilder test(StringBuilder names) {
names = names.append("4");
return names;
}
public static void main(String[] args) {
String name = "Sam";
speak(name);
System.out.println(name); //Sam
StringBuilder names = new StringBuilder("Sam");
test(names);
System.out.println(names); //Sam4
}
Because when you call speak(name);, inside speak when you do
name = name.concat("4");
it creates a new object because Strings are immutable. When you change the original string it creates a new object,I agree that you are returning it but you are not catching it.
So essentially what you are doing is :
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
try
String name = "Sam";
name = speak(name);
Of course now I think there is no need to explain why it's working with StringBuilder unless if you don't know that StringBuilder is mutable.
Looking at the Javadoc for String, one will read that
[...] String objects are immutable [...].
This means concat(String) does not change the String itself, but constructs a new String.
StringBuilders, on the other hand, are mutable. By calling append(CharSequence), the object itself is mutated.
Because String is immutable and hence String#concat does not modify the original String instance, it only returns a new String while the original is left unmodified, while StringBuilder is mutable and the change is reflected in the StringBuilder instance passed as parameter.
Okay, what is speak method doing?
First of all,
name.concat("4");
creates new object, which is equal to name, concatenated with "4".
So, the line
name = name.concat(4);
redefines local (for speak method) variable name.
Then you return the reference to this new value with
return name;
So, the original variable, passed within method is not modified, but the method returns modified value.
In the test method you actually modify variable without modifying the reference (the StringBuilder class is mutable, so variable if this type can be modified).
Then we can see another question arising: why StringBuilder.append returns value, where it can seem redundant. The answer to this question lies in the description of "builder" pattern, for which it is the usual way of implementing modification methods. See wikipedia on Builder pattern.
String is immutable in java. As soon as you invoke concat method on name. A new string is created and while you are playing with the old reference in System.out.println(name).If you want to use the modified string you should explicitly return the reference.
While StringBuilder is mutable and it returns the same reference always.
When you invoke speak(name) it computes the new value, but discards it.
If you replace it with
name = speak(name);
the result will be the one you expect.
With the StringBuilder, the object you pass is mutable: so
names.append(names);
changes the state of the current object (it also returns a reference to the same object, which is just a convenience to allow you to write code like names.append(...).append(...) etc.). So in the case of the StringBuilder, the object you are referencing when you call the method has actually changed, hence you see the changes.
In your method speak, the concat method returns a new String, the original object it was called on is unchanged (strings are immutable). As documented:
If the length of the argument string is 0, then this String object is returned. Otherwise, a String object is returned that represents a character sequence that is the concatenation of the character sequence represented by this String object and the character sequence represented by the argument string.
Calling name.concat("4") is the equivalent of name + "4".
In your test method the append method modifies the content of the StringBuilder. As documented:
The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.
In your main method both name and names are still the same object as before the method call, but the content of name is unchanged as strings are immutable, while the content of names has been changed.
If instead you had used the return values of both methods, then you would have the result you were expecting.
First of all, String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. All information in an instance is initialized when the instance is created and the information can not be modified.
Second, in java parameters are sent by values and not by reference.
In your method 'test' you don't need names = names.append("4"), instead names.append("4") will be enough .
If you check java docs for String object, you will see that most of the methods there, including concat, will generate a new String.
So to have on output Sam4 also for the String, you will need in main method to have this name = speak(name).
String
String is immutable ( once created can not be changed )object . The
object created as a String is stored in the Constant String Pool .
Every immutable object in Java is thread safe ,that implies String is
also thread safe . String can not be used by two threads
simultaneously. String once assigned can not be changed.
String demo = " hello " ; // The above object is stored in constant
string pool and its value can not be modified.
demo="Bye" ; //new "Bye" string is created in constant pool and
referenced by the demo variable // "hello" string still
exists in string constant pool and its value is not overrided but we
lost reference to the "hello"string
StringBuilder
StringBuilder is same as the StringBuffer , that is it stores the
object in heap and it can also be modified . The main difference
between the StringBuffer and StringBuilder is that StringBuilder is
also not thread safe. StringBuilder is fast as it is not thread safe
.
For more details check this
Conclusion:
You don't need to re-assign the value again to StringBuilder as it is already a reference
test method should be
public static void test(StringBuilder names) {
names.append("4");
}
but speak should be
String name = "Sam";
name = speak(name);
Must immutable objects have all properties be final?
I would say they don't. But I don't know whether I am right or not.
The main difference between an immutable object (all properties final) and an effectively immutable object (properties aren't final but can't be changed) is safe publication.
You can safely publish an immutable object in a multi threaded context without having to worry about adding synchronization, thanks to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
As a side note, it also enables to enforce immutability (if you try to mutate those fields in a future version of your class because you have forgotten it should be immutable, it won't compile).
Clarifications
Making all the fields of an object final does not make it immutable - you also need to make sure that (i) its state can't change (for example, if the object contains a final List, no mutating operations (add, remove...) must be done after construction) and (ii) you don't let this escape during construction
An effectively immutable object is thread safe once it has been safely published
Example of unsafe publication:
class EffectivelyImmutable {
static EffectivelyImmutable unsafe;
private int i;
public EffectivelyImmutable (int i) { this.i = i; }
public int get() { return i; }
}
// in some thread
EffectivelyImmutable.unsafe = new EffectivelyImmutable(1);
//in some other thread
if (EffectivelyImmutable.unsafe != null
&& EffectivelyImmutable.unsafe.get() != 1)
System.out.println("What???");
This program could in theory print What???. If i were final, that would not be a legal outcome.
You can easily guarantee immutability by encapsulation alone, so it's not necessary:
// This is trivially immutable.
public class Foo {
private String bar;
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
}
However, you also must guarantee it by encapsulation in some cases, so it's not sufficient:
public class Womble {
private final List<String> cabbages;
public Womble(List<String> cabbages) {
this.cabbages = cabbages;
}
public List<String> getCabbages() {
return cabbages;
}
}
// ...
Womble w = new Womble(...);
// This might count as mutation in your design. (Or it might not.)
w.getCabbages().add("cabbage");
It's not a bad idea to do so to catch some trivial errors, and to demonstrate your intent clearly, but "all fields are final" and "the class is immutable" are not equivalent statements.
Immutable = not changeable. So making properties final is a good idea. If not all properties of an object are protected from being changed I wouldn't say the object is immutable.
BUT an object is also immutable if it doesn't provide any setters for it's private properties.
Immutable objects MUST not be modified in any way after their creation. final of course helps to achieve that. You guarantee that they will not ever be changed. BUT what if you have an array inside your object that is final? Of course the reference is not changable, but the elements are. Look here at almost the same question I gave also:
Link
Simply declaring an object as final does not make it inherently immutable. Take for example this class:
import java.util.Date;
/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*/
public final class Planet {
public Planet (double aMass, String aName, Date aDateOfDiscovery) {
fMass = aMass;
fName = aName;
//make a private copy of aDateOfDiscovery
//this is the only way to keep the fDateOfDiscovery
//field private, and shields this class from any changes that
//the caller may make to the original aDateOfDiscovery object
fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
}
/**
* Returns a primitive value.
*
* The caller can do whatever they want with the return value, without
* affecting the internals of this class. Why? Because this is a primitive
* value. The caller sees its "own" double that simply has the
* same value as fMass.
*/
public double getMass() {
return fMass;
}
/**
* Returns an immutable object.
*
* The caller gets a direct reference to the internal field. But this is not
* dangerous, since String is immutable and cannot be changed.
*/
public String getName() {
return fName;
}
// /**
// * Returns a mutable object - likely bad style.
// *
// * The caller gets a direct reference to the internal field. This is usually dangerous,
// * since the Date object state can be changed both by this class and its caller.
// * That is, this class is no longer in complete control of fDate.
// */
// public Date getDateOfDiscovery() {
// return fDateOfDiscovery;
// }
/**
* Returns a mutable object - good style.
*
* Returns a defensive copy of the field.
* The caller of this method can do anything they want with the
* returned Date object, without affecting the internals of this
* class in any way. Why? Because they do not have a reference to
* fDate. Rather, they are playing with a second Date that initially has the
* same data as fDate.
*/
public Date getDateOfDiscovery() {
return new Date(fDateOfDiscovery.getTime());
}
// PRIVATE //
/**
* Final primitive data is always immutable.
*/
private final double fMass;
/**
* An immutable object field. (String objects never change state.)
*/
private final String fName;
/**
* A mutable object field. In this case, the state of this mutable field
* is to be changed only by this class. (In other cases, it makes perfect
* sense to allow the state of a field to be changed outside the native
* class; this is the case when a field acts as a "pointer" to an object
* created elsewhere.)
*/
private final Date fDateOfDiscovery;
}
No.
For example, see the implementation of java.lang.String. Strings are immutable in Java, but the field hash is not final (it is lazily computed the first time hashCode is called and then cached). But this works because hash can take on only one nondefault value that is the same every time it is computed.
String class is Immutable but property hash is not final
Well it is possible but with some rules/restrictions and that is access to mutable properties/fields must provide same result every time we access it.
In String class hashcode actually calculated on the final array of characters which is not going to change if String has constructed. Therefore immutable class can contain mutable fields/properties but it has to make sure that access to field/property will produce the same result every time it is accessed.
To answer your question it is not mandatory to have all the fields final in a immutable class.
For further reading visit here [blog] : http://javaunturnedtopics.blogspot.in/2016/07/string-is-immutable-and-property-hash.html
Not necessary, you can achieve same functionality by making member as non-final but private and not modifying them except in constructor. Don't provide setter method for them and if it is a mutable object, then don't ever leak any reference for that member.
Remember making a reference variable final, only ensures that it will not be reassigned a different value, but you can still change individual properties of an object, pointed by that reference variable. This is one of the key points.
I saw following member in java.lang.String :
private final char value[];
My question is:
Will following statement make a copy of the literal string into char[] metioned above, while another copy of literal string also exists in the constant pool.
String b1 = new String("abc");
If so, didn't the constant pool meaning less? Or we should prevent use new() to create String with literal?
#Update:
So, according to the answers, why String class need a char value[] variable inside it, why not just refer to a single copy inside constant pool?
If create a string with new String("..."), won't the literal be put into constant pool if not exists in pool yet?
According to my imagine, the only benefit to use the new String() is that, it might be quicker than query a constant pool; or the constant pool has size limit, it will remove old constant value when size not enough? But I am not sure is this the way it works.
Conclusion
So, according to answers the new String() should only be used by constant pool maintainer itself, we programmers don't.
You can use new, but it will be a little tricky that you specify using the "intern" method of String.
like this:
String a = "ABC";
String b = new String("ABC").intern();
System.out.println(a == b);
Output is true, if no "intern", then it is a copy from the constant pool.
String a = "ABC";
String b = new String("ABC");
System.out.println(a == b);
output is false.
If you looks into the prototype of this String constructor, it shows that:
/**
* Initializes a newly created {#code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {#code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* #param original
* A {#code String}
*/
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
Latter is right. To create a String instance from literal using new() is absolutely meaningless.
String in java are like any other programming language, a sequence of
characters. This is more like a utility class to work on that char
sequence. This char sequence is maintained in following variable:
/** The value is used for character storage. */
private final char value[];
When you create the String with new keyword like this
String b1 = new String("abc");
then Object is created into the Heap Memory , and when Java Compiler encounters any String literal , It creates one Object inside constant pool
Now b1 is pointing to the Object inside Heap Memory , and since a String literal is also there so an Object also created in constant pool to whom no one is pointing
As Effective java 2nd Edition Says
String s = new String("neerajjain"); //DON'T DO THIS!
because you are unnecessarily creating 2 objects when work can be done by only 1 Object .
but there are some cases where you might use new String("string") you can find them here
Must immutable objects have all properties be final?
I would say they don't. But I don't know whether I am right or not.
The main difference between an immutable object (all properties final) and an effectively immutable object (properties aren't final but can't be changed) is safe publication.
You can safely publish an immutable object in a multi threaded context without having to worry about adding synchronization, thanks to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
As a side note, it also enables to enforce immutability (if you try to mutate those fields in a future version of your class because you have forgotten it should be immutable, it won't compile).
Clarifications
Making all the fields of an object final does not make it immutable - you also need to make sure that (i) its state can't change (for example, if the object contains a final List, no mutating operations (add, remove...) must be done after construction) and (ii) you don't let this escape during construction
An effectively immutable object is thread safe once it has been safely published
Example of unsafe publication:
class EffectivelyImmutable {
static EffectivelyImmutable unsafe;
private int i;
public EffectivelyImmutable (int i) { this.i = i; }
public int get() { return i; }
}
// in some thread
EffectivelyImmutable.unsafe = new EffectivelyImmutable(1);
//in some other thread
if (EffectivelyImmutable.unsafe != null
&& EffectivelyImmutable.unsafe.get() != 1)
System.out.println("What???");
This program could in theory print What???. If i were final, that would not be a legal outcome.
You can easily guarantee immutability by encapsulation alone, so it's not necessary:
// This is trivially immutable.
public class Foo {
private String bar;
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
}
However, you also must guarantee it by encapsulation in some cases, so it's not sufficient:
public class Womble {
private final List<String> cabbages;
public Womble(List<String> cabbages) {
this.cabbages = cabbages;
}
public List<String> getCabbages() {
return cabbages;
}
}
// ...
Womble w = new Womble(...);
// This might count as mutation in your design. (Or it might not.)
w.getCabbages().add("cabbage");
It's not a bad idea to do so to catch some trivial errors, and to demonstrate your intent clearly, but "all fields are final" and "the class is immutable" are not equivalent statements.
Immutable = not changeable. So making properties final is a good idea. If not all properties of an object are protected from being changed I wouldn't say the object is immutable.
BUT an object is also immutable if it doesn't provide any setters for it's private properties.
Immutable objects MUST not be modified in any way after their creation. final of course helps to achieve that. You guarantee that they will not ever be changed. BUT what if you have an array inside your object that is final? Of course the reference is not changable, but the elements are. Look here at almost the same question I gave also:
Link
Simply declaring an object as final does not make it inherently immutable. Take for example this class:
import java.util.Date;
/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*/
public final class Planet {
public Planet (double aMass, String aName, Date aDateOfDiscovery) {
fMass = aMass;
fName = aName;
//make a private copy of aDateOfDiscovery
//this is the only way to keep the fDateOfDiscovery
//field private, and shields this class from any changes that
//the caller may make to the original aDateOfDiscovery object
fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
}
/**
* Returns a primitive value.
*
* The caller can do whatever they want with the return value, without
* affecting the internals of this class. Why? Because this is a primitive
* value. The caller sees its "own" double that simply has the
* same value as fMass.
*/
public double getMass() {
return fMass;
}
/**
* Returns an immutable object.
*
* The caller gets a direct reference to the internal field. But this is not
* dangerous, since String is immutable and cannot be changed.
*/
public String getName() {
return fName;
}
// /**
// * Returns a mutable object - likely bad style.
// *
// * The caller gets a direct reference to the internal field. This is usually dangerous,
// * since the Date object state can be changed both by this class and its caller.
// * That is, this class is no longer in complete control of fDate.
// */
// public Date getDateOfDiscovery() {
// return fDateOfDiscovery;
// }
/**
* Returns a mutable object - good style.
*
* Returns a defensive copy of the field.
* The caller of this method can do anything they want with the
* returned Date object, without affecting the internals of this
* class in any way. Why? Because they do not have a reference to
* fDate. Rather, they are playing with a second Date that initially has the
* same data as fDate.
*/
public Date getDateOfDiscovery() {
return new Date(fDateOfDiscovery.getTime());
}
// PRIVATE //
/**
* Final primitive data is always immutable.
*/
private final double fMass;
/**
* An immutable object field. (String objects never change state.)
*/
private final String fName;
/**
* A mutable object field. In this case, the state of this mutable field
* is to be changed only by this class. (In other cases, it makes perfect
* sense to allow the state of a field to be changed outside the native
* class; this is the case when a field acts as a "pointer" to an object
* created elsewhere.)
*/
private final Date fDateOfDiscovery;
}
No.
For example, see the implementation of java.lang.String. Strings are immutable in Java, but the field hash is not final (it is lazily computed the first time hashCode is called and then cached). But this works because hash can take on only one nondefault value that is the same every time it is computed.
String class is Immutable but property hash is not final
Well it is possible but with some rules/restrictions and that is access to mutable properties/fields must provide same result every time we access it.
In String class hashcode actually calculated on the final array of characters which is not going to change if String has constructed. Therefore immutable class can contain mutable fields/properties but it has to make sure that access to field/property will produce the same result every time it is accessed.
To answer your question it is not mandatory to have all the fields final in a immutable class.
For further reading visit here [blog] : http://javaunturnedtopics.blogspot.in/2016/07/string-is-immutable-and-property-hash.html
Not necessary, you can achieve same functionality by making member as non-final but private and not modifying them except in constructor. Don't provide setter method for them and if it is a mutable object, then don't ever leak any reference for that member.
Remember making a reference variable final, only ensures that it will not be reassigned a different value, but you can still change individual properties of an object, pointed by that reference variable. This is one of the key points.