Unless you already have a String object called apple, the first line won't compile. You ought to have written "apple". If you already have a String called apple, what it means is, "I want to apply the name s1 to the String object I have already got which I have previously called apple". You now have two names for the same Object.
The first line means "I want a String and I want it to read apple," and the second line means "I want a String distinct from any other Strings and I want it to read apple". If you already have a String with the content apple, the JVM may use the same String again, just with a new name s1. Note this behaviour occurs with Strings only. There is rather similar behaviour if you use the valueOf() method of "wrapper" classes like Integer.
Originally posted by qingwu wang: ...="apple"; is created in the STACK ...=new String("apple"); is created in the HEAP
See the article I referenced above.
Objects are created on the heap and Strings are no exception. So, Strings that are part of the "String Literal Pool" still live on the heap, but they have references to them from the String Literal Pool.
When a class is loaded (note that loading happens prior to initialization), the JVM goes through the code for the class and looks for String literals. When it finds one, it checks to see if an equivalent String is already referenced from the heap. If not, it creates a String instance on the heap and stores a reference to that object in the constant table.