Java know that the "java" string already exists in constant pool, so it needs not to create the object again?
Actually, it's not "java" string that exists in the pool, but "Java" (in uppercase). If it were indeed "java", toLowerCase() would have recognized it, and returned the original string. But since the return value (i.e. "java" in all lowercase) does not match the original string (i.e. "Java" in mixed case) a new String object needs to be created, bringing the count to 4.
Edit: After the edit to the question the answer changes: now that you've changed "Java" to "java", the number of objects that get created is three, because Java String has an optimization that returns the original string from toLowerCase when the string is already in lowercase. So line 1 creates one string object "java", line 2 creates two string objects " SE 6" and "java SE 6", and lines 3 and 4 do not create any additional objects.
s.toLowerCase()returns a new String object.concat, so s will be "java" and then"java",toLowerCase()will return the same String "java"toLowerCase()and seen that there is areturn thisline in it when it finds nothing to do. My bad.