static final String = "something";
I was wondering if such a declaration has some kind real sense in Java. I've found it thousands of time within the code but studying and playing with strings I've learnt that does not matter how many times you declare a String object: if some class before yours declared this string this is pooled and reused (I'm talking about String created without explicit constructor invocation)
public class StringCompare {
private void toCompare(String h) {
String x = "hello";
System.out.println( x == h);
}
public void compare() {
String h = "hello";
toCompare(h);
}
}
This code, in fact, prints true when calling compare so the 2 variables are referencing the same object. Said that a final variable can't be redefined, the static word is completely useless in this case. Am I missing the point?
Couple of more things:
1 - Why explicit call to String constructor won't cause the String to be pooled? Same code above using a new String("hello") print false.
2 - Is the pooling behaviour reserved to Strings? There are some other immutable objects (like BigInteger) but I think these are not pooled ... why?
Thanks,
Carlo
There are a few reasons why developers use this pattern, even though your analysis of the runtime behavior and its use the string pool is correct.
It communicates the developers intent more cleanly. Specifically the string now has a name that is hopefully more clear than the constant, and it communicates the runtime behaviour that not everybody is aware of (or they forget from time to time).
If the developer wants to change the value within the source file, and it has been used in multiple places then there is only one place to make that change.
Once the decision to use a variable has been made, the keyword static will mean that the memory usage is lower. That is, there is only one field used to store the ref rather than one field per instance of the object.
As for your follow on questions:
Q: Why explicit call to String constructor won't cause the String to be pooled? Same code above using a new String("hello") print false.
Because the string pool is only used for string literals, as described by the JLS and invoking a constructor is not classified as a string literal.
Q: Is the pooling behaviour reserved to Strings?
The string pool is only used for string literals, but there is of course other caches for different use cases. The most obvious one that jumps to mind is the int cache used to optimize auto boxing of ints.
Even if the static doesn't give you a memory benefit in this case, you can still access the field in a static way, so you don't need an instance. For example, you frequently use some URIs, so you create the following class:
public class Uris
{
public static final String GOOGLE = "http://google.com";
public static final String BBC = "http://bbc.co.uk";
}
Using static, you can just use Uris.GOOGLE instead of new Uris().GOOGLE.
The static means that for each new object created for that class, the String construction & pooling only has to happen once, ever. This is a small saving in computation.
it is because String ="hello" or String h are not creating any object in heap these all are stored inString constant pool where as new String("hello"); create a new object in heap and so address will be different
check details here
String x = "hello";
String h = "hello";
are two String literals. They are in common pool(part of String pool). There are referring same reference. Then == check the reference you will get true
If you use String x = new String("hello"), it will create a new String object x. of course referring new reference. Now compare reference give you false.
Related
While writing code i came across an interesting problem.
I have a PersonPOJO with name as one of its String members with its getters and setters
class PersonPOJO {
private String name;
public setName(Name) {
this.name = Name;
}
public getName() {
return name;
}
}
Now i am using it in Test class. There are two approach of using String getters in it.
Approach 1 :-
class Test1 {
............
String name = personPojo.getName();
logger.debug("....."+name);
if (name.equals("ABC")) {
....
}
}
Approach 2 :-
class Test2 {
.............
logger.debug("...."+personPojo.getName());
if (personPojo.getName.equals("ABC")) {
..
}
}
Thus in second approach i am not creating intermediate String variable. Will not creating an extra String variable helps in performance like no extra String object creation , less load on GC etc.
Please explain in detail which approach is better ?
Thanks,
there is nothing extra getting created anywhere except the "ABC" literal that you have in your if check. See the 'name' is just a reference to a String object to which personPojo.getName() points. So in terms of memory there are no dents.
However calling personPojo.getName() again and again in second example does have a performance hit as compared to option 1. Local variables reside on stack and are often the fastest to access as compared to getting an object form heap and then calling a method on it.
Since the other answers already answered your question, some additional information regarding strings in Java:
Strings in java are special. There are 2 ways of creatings Strings:
1. implicit via string literal
String literal = "Some text";
and
2. explicit via new()
String explicit = new String("Some text");
While string literals are kept in a so called string common pool, string objects created via new are kept in the heap like any other object. This means if you have three different string literals
String literal1 = "Test";
String literal2 = "Test";
String literal3 = "Test";
and each of em have the same content, they all share the same storage inside the string common pool.
Like I mentioned just some additional information, but always good to know. :D
In both the approaches you are not creating any new String object. When you say :
String name = personPojo.getName();
name is a reference to personPojo.name Object on heap. It doesnt creates intermediate string.
Also this reference "name" becomes eligible for GC as program control goes out of scope
Thus both the cases are similar performance wise and memory wise.
The only point where you create an intermediate String variable is your debug code. What you do is a reference copy, which is about the same as writing:
int myStringRef = personPojo.getName();
And that really doesn't take any significant time to execute, especially not since the JVM is likely to remove that extra variable anyways. Hint: If you want to make it even more likely, add a final in front of it.
If you want to improve it even further, make the PersonPOJO object immutable by declaring the name as final and remove the setter.
And then both suggestions will increase speed by such a low amount that even with the best tool you wouldn't be able to notice it.
You are not creating an object in either example. Neither are you altering an object. You are merely creating a local variable reference.
As for the created reference, the difference is not as big as you might think. The Java run time will optimize this additional reference away eventually and even if it was not doing that, you would never notice the difference. When writing code, do not think about those things. Rather think about the readability of your code.
String name = personPojo.getName();
logger.debug("....."+name);
if (name.equals("ABC"))
logger.debug("...."+personPojo.getName());
if (personPojo.getName.equals("ABC")) {
Both cases are same w.r.t. performance is concern. Because by String name = personPojo.getName(); you are not creating a new object rather you are just creating a new reference to the same string Object.
May be String name = personPojo.getName(); is little bit better because you not calling the function again and again rather using a local variable. Here it may not have much impact, may be negligible but it good not to call the same function again and again.
For the below statement in a program, how many objects will be created in heap memory and in the string constant pool?
I need clarity in object creation. Many sources I've read are not elaborating. I am confused when the object gets destroyed.
String a="MAM"+"BCD"+"EFG"+"GFE";
How many objects will be created?
I am looking for good material about the life cycle of objects, methods and classes and how the JVM handles them when they are dynamically changed and modified.
"MAM"+"BCD"+"EFG"+"GFE" is a compile-time constant expression and it compiles into "MAMBCDEFGGFE" string literal. JVM will create an instance of String from this literal when loading the class containing the above code and will put this String into the string pool. Thus String a = "MAM"+"BCD"+"EFG"+"GFE"; does not create any object, see JLS 15.18.1. String Concatenation Operator +
The String object is newly created (§12.5) unless the expression is a compile-time constant expression (§15.28).
It simply assigns a reference to String object in pool to local var a.
Only one object is created.
string s1 = "java";
string s2 = "ja" + "va";
s.o.p(s1==s2);
The statement yields true.
String s1="java";
string s2 = "ja";
String s3 = s2 +"va";
s.o.p(s1==s3);
The statement yields false.
So minimum one apparent should be permanent, then '+' operator generates new string object (in non constant pool using new()).
So, the question you asked does not have one also permanent. This means it creates only one object.
Exactly one object is created and placed in the constant pool, unless it already exists, in which case the existing object is used. The compiler concatenates string constants together, as specified in JLS 3.10.5 and 15.28.
A long string literal can always be broken up into shorter pieces and written as a (possibly parenthesized) expression using the string concatenation operator +
http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5
Most answers seem to focus that a) the complete expression is one compile time constant and b) that the line itself does not construct a new object but only a reference to one object.
However noone so far has mentioned, that String itself contains a reference to an internal char[] (which is also in the constant pool).
Summary: There are two objects in the constant pool (String and char[]). The line does neither create nor destroy any object.
And regarding:
I am confused when the object gets destroyed.
No object is destroyed, since stuff in the constant pool will only be destroyed if the class itself would be unloaded. At most you can say, that the reference a will go out of scope eventually.
Only one object will be created since String a will compile into "MAMBCDEFGGFE".
Answers stating a single heap object in your example are correct. However, consider this code:
public class Tester
{
public String a="MAM";
public String b ="BCD";
public String c = "EFG";
public String d ="GFE";
public Tester()
{
String abcd = a + b + c + d;
}
}
In this example, there are 7 strings being created. a,b,c and d are not compiled into a single constant - they are members. 1 string is then created for each + operator - semantically speaking, + is a concatenation but logically it is creating a new string in memory. The first 2 operator strings are discarded immediately and are now eligible for garbage collection but the memory churn still occurs.
Technically there in an 8th object. The instance of Tester.
Edit: This has been proved to be nonsense in the comments
If you answer "yes", then give an example of how you can change a String.
If you answer "no", then explain why the Java designers don't let us modify Strings
No.
Strings are immutable by design. If you want to alter a string, I suggest you look at the StringBuffer class.
Immutable is a design pattern. As multiple entities can reference an object, immutability ensures that the object you reference has not been altered by some other object that references it.
No, you cannot modify a string after you create it. String is an example of an immutable class. If you have the following code:
String a = "hello";
String b = a;
a and b are now referencing the same object, but there is nothing that you can do to a that will change the string that b is referencing. You can only assign a to a different string.
I can only speculate about why the Java designers chose to have it this way, but I suspect a major reason is to facilitate code predictability. If you had something like this.
String h = "house";
String hcopy = h;
and at some later point you were able to modify h in some way like h.splitInHalf() that actually changed h's string, that would also affect hcopy and make things very frustrating when simple String variables changed values without warning.
If you would like a String-like structure that you can modify, you can use StringBuffer.
You can't not,each time you try to change it,a new String object is actually created.If you want to use changable String,use StringBuffer,StringBuilder instead.
There is a String constant pool in memory for better performence.
In my experience, that's a popular interview question. The objective is to figure out whether the interviewee knows the internals of the java.lang.String class.
So to answer the question, by design, Java does not allow to change a String object, those objects are immutable. However, though you should never do it in a real production code, it is technically possible to change a String object using the Reflection API.
import java.lang.reflect.Field;
public class App {
public static void main(String[] args) throws Exception {
String str = "Hello world!";
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] c = (char[]) valueField.get(str);
c[1] = 'a';
System.out.println(str); //prints Hallo world!
}
}
As is often said, Java will let you shoot yourself in the foot after you use a magic spell of "import java.lang.reflect.*;"
I am new in java.
In java, String is a class.But
we do not have to use new keyword to create an object of class String where as new is used for creating objects for other classes.
I have heard about Wrapper classes like Integer,Double which are similar to this.
But String is not Wrapper,isn't it?
Actually what is happening when i use
String message = "Hai";
??
How it is different from
String message = new String("Hai");
Here is message a reference variable or something else??
Are there other classes which do not require new to create object ??
With the following line you are not creating a new String object in the heap but reusing a string literal (if already available):
String message = "Hai";
"Hai" is a string literal in the string literal pool. Since, strings are immutable, they are reusable so they are pooled in the string literal pool by the JVM. And this is the recommended way, because you are reusing it.
But, with the following you are actually creating a new object (in the heap):
String message = new String("Hai");
new String("Hai") is a new String object. In this case, even if the literal "Hai" was already in the string literal pool, a new object is created. This is not recommended because chances are that you might end with more than one String objects with the same value.
Also see this post: Questions about Java's String pool
Are there other classes which do not require new to create object ??
Actually, you can not create any object in Java without using the keyword new.
e.g.
Integer i = 1;
Does, not mean that the Integer object is created without using new. It's just not required for us to use the new keyword explicitly. But under the hood, if the Integer object with value 1 does not already exist in cache (Integer objects are cached by JVM), new keyword will be used to create it.
The Java language specification allows for representation of a string as a literal. You can consider it a shortcut initialization for a String that has one important side-effect that is different from regular initialization via new
String literals are all interned, which means that they are constant values stored by the Java runtime and can be shared across multiple classes. For example:
class MainClass (
public String test = "hello";
}
class OtherClass {
public String another = "hello";
public OtherClass() {
MainClass main = new MainClass();
System.out.println(main.test == another);
}
}
Would print out "true" since, both String instances actually point to the same object. This would not be the case if you initialize the strings via the new keyword.
String and Integer creation are different.
String s = "Test";
Here the '=' operator is overloaded for string. So is the '+' operator in "some"+"things".
Where as,
Integer i = 2;
Until Java 5.0 this is compile time error; you cant assign primitive to its wrapper. But from Java 5.0 this is called auto-boxing where primitives are auto promoted to their wrappers wherever required.
String h1 = "hi";
will be different from
String h2 = new String("hi");
The reason is that the JVM maintains a string table for all string literals. so there will be an entry in the table for "hi" , say its address is 1000.
But when you explicitly create a string object, new object will be created, say its address is 2000. Now the new object will point to the entry in the string table which is 1000.
Hence when you say
h1 == h2
it compares
1000 == 2000
So it is false
In java
"==" compares the left & right hand sides memory locations(and not the value at that memory location) and therefore in case of
new String("hai")==new String("hai")
it returns false.
In case of "Hai"=="Hai", java doesn't allocate separate memory for same string literal therefore here "==" returns true. You can always use equals method to compare values.
The reason why doesn't recommended because of memory, using new keyword and creating String object, JVM create 2 object between HEAP and SCP, but using just literal is that JVM creating only SCP. That's why we creating String object, just using literal.
While looking at online code samples, I have sometimes come across an assignment of a String constant to a String object via the use of the new operator.
For example:
String s;
...
s = new String("Hello World");
This, of course, compared to
s = "Hello World";
I'm not familiar with this syntax and have no idea what the purpose or effect would be.
Since String constants typically get stored in the constant pool and then in whatever representation the JVM has for dealing with String constants, would anything even be allocated on the heap?
The one place where you may think you want new String(String) is to force a distinct copy of the internal character array, as in
small=new String(huge.substring(10,20))
However, this behavior is unfortunately undocumented and implementation dependent.
I have been burned by this when reading large files (some up to 20 MiB) into a String and carving it into lines after the fact. I ended up with all the strings for the lines referencing the char[] consisting of entire file. Unfortunately, that unintentionally kept a reference to the entire array for the few lines I held on to for a longer time than processing the file - I was forced to use new String() to work around it, since processing 20,000 files very quickly consumed huge amounts of RAM.
The only implementation agnostic way to do this is:
small=new String(huge.substring(10,20).toCharArray());
This unfortunately must copy the array twice, once for toCharArray() and once in the String constructor.
There needs to be a documented way to get a new String by copying the chars of an existing one; or the documentation of String(String) needs to be improved to make it more explicit (there is an implication there, but it's rather vague and open to interpretation).
Pitfall of Assuming what the Doc Doesn't State
In response to the comments, which keep coming in, observe what the Apache Harmony implementation of new String() was:
public String(String string) {
value = string.value;
offset = string.offset;
count = string.count;
}
That's right, no copy of the underlying array there. And yet, it still conforms to the (Java 7) String documentation, in that it:
Initializes a newly created 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 original is needed, use of this constructor is unnecessary since Strings are immutable.
The salient piece being "copy of the argument string"; it does not say "copy of the argument string and the underlying character array supporting the string".
Be careful that you program to the documentation and not one implementation.
The only time I have found this useful is in declaring lock variables:
private final String lock = new String("Database lock");
....
synchronized(lock)
{
// do something
}
In this case, debugging tools like Eclipse will show the string when listing what locks a thread currently holds or is waiting for. You have to use "new String", i.e. allocate a new String object, because otherwise a shared string literal could possibly be locked in some other unrelated code.
String s1="foo"; literal will go in StringPool and s1 will refer.
String s2="foo"; this time it will check "foo" literal is already available in StringPool or not as now it exist so s2 will refer the same literal.
String s3=new String("foo"); "foo" literal will be created in StringPool first then through string arg constructor String Object will be created i.e "foo" in the heap due to object creation through new operator then s3 will refer it.
String s4=new String("foo"); same as s3
so System.out.println(s1==s2); //true due to literal comparison.
and System.out.println(s3==s4);// false due to object comparison(s3 and s4 is created at different places in heap)
The sole utility for this constructor described by Software Monkey and Ruggs seems to have disappeared from JDK7.
There is no longer an offset field in class String, and substring always use
Arrays.copyOfRange(char[] original, int from, int to)
to trim the char array for the copy.
Well, that depends on what the "..." is in the example. If it's a StringBuffer, for example, or a byte array, or something, you'll get a String constructed from the data you're passing.
But if it's just another String, as in new String("Hello World!"), then it should be replaced by simply "Hello World!", in all cases. Strings are immutable, so cloning one serves no purpose -- it's just more verbose and less efficient to create a new String object just to serve as a duplicate of an existing String (whether it be a literal or another String variable you already have).
In fact, Effective Java (which I highly recommend) uses exactly this as one of its examples of "Avoid creating unnecessary objects":
As an extreme example of what not to do, consider this statement:
String s = new String("stringette"); **//DON'T DO THIS!**
(Effective Java, Second Edition)
Here is a quote from the book Effective Java Third Edition (Item 17: Minimize Mutability):
A consequence of the fact that immutable objects can be shared freely
is that you never have to make defensive copies of them (Item
50). In fact, you never have to make any copies at all because the
copies would be forever equivalent to the originals. Therefore, you
need not and should not provide a clone method or copy constructor
(Item 13) on an immutable class. This was not well understood in the
early days of the Java platform, so the String class does have a copy
constructor, but it should rarely, if ever, be used.
So It was a wrong decision by Java, since String class is immutable they should not have provided copy constructor for this class, in cases you want to do costly operation on immutable classes, you can use public mutable companion classes which are StringBuilder and StringBuffer in case of String.
Generally, this indicates someone who isn't comfortable with the new-fashioned C++ style of declaring when initialized.
Back in the C days, it wasn't considered good form to define auto variables in an inner scope; C++ eliminated the parser restriction, and Java extended that.
So you see code that has
int q;
for(q=0;q<MAX;q++){
String s;
int ix;
// other stuff
s = new String("Hello, there!");
// do something with s
}
In the extreme case, all the declarations may be at the top of a function, and not in enclosed scopes like the for loop here.
IN general, though, the effect of this is to cause a String ctor to be called once, and the resulting String thrown away. (The desire to avoid this is just what led Stroustrup to allow declarations anywhere in the code.) So you are correct that it's unnecessary and bad style at best, and possibly actually bad.
There are two ways in which Strings can be created in Java. Following are the examples for both the ways:
1) Declare a variable of type String(a class in Java) and assign it to a value which should be put between double quotes. This will create a string in the string pool area of memory.
eg: String str = "JAVA";
2)Use the constructor of String class and pass a string(within double quotes) as an argument.
eg: String s = new String("JAVA");
This will create a new string JAVA in the main memory and also in the string pool if this string is not already present in string pool.
I guess it will depend on the code samples you're seeing.
Most of the times using the class constructor "new String()" in code sample are only to show a very well know java class instead of creating a new one.
You should avoid using it most of the times. Not only because string literals are interned but mainly because string are inmutable. It doesn't make sense have two copies that represent the same object.
While the article mensioned by Ruggs is "interesting" it should not be used unless very specific circumstances, because it could create more damage than good. You'll be coding to an implementation rather than an specification and the same code could not run the same for instance in JRockit, IBM VM, or other.