Original: Create Java String Using ” ” or Constructor? By X Wang In Java, a string can be created using two methods:
String x = "abc";
String y = new String("abc");
What is the difference between using double quotes and using a constructor?
1. Double Quotes vs. Constructor
This question can be answered by considering two simple examples. Example 1:String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
a==b
true because a
both b
refer to the same object - a string declared as a literal (string literal below) in the method area (we refer the reader to the source on our resource: Top 8 diagrams for understanding Java , diagram 8). When the same string literal is created more than once, only one copy of the string is stored in memory, only one instance of it (in our case "abcd"). This is called "string interning". All string constants processed at compile time are interned automatically in Java. Example 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True
c==d
false because c
and d
refer to two different objects in memory (on the heap). Different objects always have different references. This diagram illustrates the two situations described above:
2. Interning strings at the stage of program execution
The author thanks LukasEder (the comment below is his own): String interning can also occur at runtime, even if the two strings are created using constructors:String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
3. When to use double quotes and when to use constructors
Because the literal "abcd" is always of type String, using the constructor will create an additional unnecessary object. So double quotes should be used if you just need to create a string. If you really need to create a new object on the heap, you must use a constructor. Here (original) the use cases are shown. (The translated text is given below. But still I highly recommend that you familiarize yourself with the code of the commentators at this link.)substring() method in JDK 6 and JDK 7
The substring() Method in JDK 6 and JDK 7 By X Wang The methodsubstring(int beginIndex, int endIndex)
in JDK 6 and JDK 7 is different. Knowing these differences can help you make better use of this method. For the sake of readability, below substring()
we will mean the full syntax, i.e. substring(int beginIndex, int endIndex)
.
1. What does substring() do?
The methodsubstring(int beginIndex, int endIndex)
returns a string that starts with the character numbered beginIndex
and ends with the character numbered endIndex-1
.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
output:
bc
2. What happens when substring() is called?
You may know that, due to immutability ,x
assigning the result to x points to an entirely new row (see diagram): However, this diagram is not entirely correct; it doesn't show what's really going on in the heap. What actually happens when is called is different in JDK 6 and JDK 7. x.substring(1,3)
x
substring()
3. substring() in JDK 6
The string type is supported by an array of typechar
. In JDK 6, the class String
contains 3 fields: char value[]
, int offset
, int count
. They are used to store the actual array of characters, the index of the first character in the array, the number of characters in the string. When the method is called substring()
, it creates a new string, but the value of the variable still points to the same array on the heap. The difference between the two strings is their number of characters and the index value of the starting character in the array. The code below is simplified and only contains the basics to demonstrate the problem.
//JDK 6
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
//check boundary
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
4. Problem caused by substring() in JDK 6
If you have a VERY long string but only want a small part of it that you get every time you usesubstring()
. This will cause runtime problems, since you need a small part, you still have to store the entire string. For JDK 6, the solution is the following code, which will cast the string to a true substring:
x = x.substring(x, y) + ""
The user STepeR formulated a question (see his comment), and it seemed necessary to supplement point 4. "Issue Caused substring()
in JDK 6" is a more extensive example. I hope this will be the answer and help others quickly figure out what the essence of the problem is. Here is the code:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
So, in JDK 7 b
, objects с
of type String
created as a result of calling a method substring()
on object a of type String
will refer to two newly created arrays in the heap - L
for b
, ongL
for c
. These two new arrays will be stored in the heap ALONG WITH the original array aLongLongString
referenced by a. Those. the original array does not disappear anywhere. Now back to JDK 6. In JDK 6, there is a single array in a heap aLongLongString
. After executing lines of code
String b = a.substring(1, 2);
String c = a.substring(2, 6);
objects b
, c
all refer to the same array in the heap corresponding to the object a
: b
- to elements from the 1st index to the 2nd, c
- to the elements from the 2nd index to the 6th (numbering starts from 0, reminder). Those. it is obvious that any further access to variables b
or c in JDK 6 will actually lead to "counting" the desired elements of the original array in the heap. In JDK 7, any further access to variables b
or c will cause access to the required smaller arrays that have already been created and "live" in the heap. Those. clearly JDK 7 uses physically more memory in situations like this. But let's imagine a possible option: variables b
and c
are assigned some substrings of the variablea
, and in the future everyone uses only them - objects b
and c
. The variable a is simply no longer accessed, there are no references to it (this is what the author of the article means). As a result, at some point in time, the garbage collector is triggered, and (in the most general form, of course) we get 2 different situations: JDK 6 : the object is destroyed (garbage collected) a
, BUT - the original huge array in the heap is alive; it is constantly used b
and c
. JDK 7: Destroyed object a along with original array in heap. This is the point in JDK 6 that can lead to a memory leak.
5. substring() in JDK 7
The method has been improved in JDK 7. In JDK 7substring()
it actually creates a new array on the heap.
//JDK 7
public String(char value[], int offset, int count) {
//check boundary
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
//check boundary
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
GO TO FULL VERSION