Strings inner workings, and the substring method - 1

"Hi, Amigo!"

"Hi, Ellie."

"I'm going to tell you about substrings. A substring is a part of a string. And the most common operation performed on strings (after combining several strings together) is obtaining a substring."

7) How do I get part of a String?

"The substring method returns part of a String. This method has two versions."

"The first version returns the substring specified by starting and ending indices. But the character at the ending index is not included! If you pass the numbers 1 and 3, then the substring will only contain the second and third characters (remember the indices start with 0)."

"The second version returns the substring starting from the passed index until the end of the String."

Method(s) Example(s)
String substring(int beginIndex, int endIndex)
String s = "Good news, everyone!";
s = s.substring(1,6);
Result:

s == "ood n";
String substring(int beginIndex)
String s = "Good news, everyone!";
s = s.substring(1);

"That's simple enough. Thanks, Ellie."

"I'm also going to explain the internal workings of String objects to you."

"As you probably already know, String is an immutable class. And what advantages does that give us? As it happens, one of the key advantages is the ability to get a substring. But first things first."

"Internally, a String object contains an array of characters, which isn't that hard to guess. But it also stores two more variables: the index of the first character in the array and the character count. Now I will tell you what these are used for."

"When we create a substring using the substring method, a new String object is created."

"But, instead of storing a reference to a new character array, the object stores a reference to the old array as well as two variables that it uses to determine the part of the original character array that is associated with it."

"I didn't understand any of that."

"When a substring is created, the character array is not copied to the new String object. Instead, both objects store a reference to the original character array. But! The second object also stores two variables: its starting index in the array and the number of characters that belong to the substring."

"Check it out:"

Getting a substring What's stored inside the substring
String s = "mama";
What's stored in s:

char[] value = {'m','a','m','a'};
offset = 0;
count = 4;
String s2 = s.substring(1);
What's stored in s2:

char[] value = {'m','a','m','a'};
offset = 1;
count = 3;
String s3 = s.substring(1, 3);
What's stored in s3:

char[] value = {'m','a','m','a'};
offset = 1;
count = 2;

"All three Strings store a reference to the same char array, but they also store the index of the first and last characters that pertain to them. Or more accurately, the index of the first character and the character count."

"That makes sense now."

"So, if you take a String that is 10,000 characters long and you create 10,000 substrings of any length, these substrings will use very little memory, because the character array is not duplicated. These Strings, which you would expect to use up a lot of space, will literally only take a couple of bytes."

"Cool!"

"But could you do that if you could modify Strings?"

"No, someone could change the first String, and then all of its substrings would change too. Now it make sense why they did that. That is a really cool solution."

"I'm glad you liked it."