String
’s are our first example of a reference type in java. These are more complicated data types that can do much more than simply hold a value.
To understand the difference between primitive and reference types, it helps to think about how variables actually work. When you run a program in java, it builds a special table in memory called a Variable Lookup Table. Imagine this looks like the table below:
name | type | size | value |
---|---|---|---|
a |
int |
32 |
0010... (32 bits) |
b |
char |
16 |
1001... (16 bits) |
c |
String |
64 |
1010... (64 bits) |
When you use a variable in your program, java goes to this table and says “hmmm, it looks like a
is a 32-bit integer type, so lets interpret these 32 0
’s and 1
’s as an integer.”
With a primitive type, the value stored in the lookup table is the actual value of the variable. This works because primitive types always have the same, known size. Most of the types mentioned above are primitive, except String
.
For a reference types, though, like a String
, the value stored in the table is an address of another spot in memory (called the heap). The heap is used to store more complicated pieces of data that may have lots of individual components, or be an unknown size. When java looks up c
, it reads the address, then performs ANOTHER lookup to actually find the beginning of the actual String
data. This allows you to work with the String
in far more complex and powerful ways than when you work with the int
data. Specifically, it means that strings have their own methods.
We will use CS Awesome lesson 2.7 for additional details and practice on these notes.
To call a string method, you will take a string literal such as "Hi there"
OR a variable of type string, add a period then a method name with parameters. So for example, you could do the following:
1
2
3
4
5
int l = "Hi there".length(); //l is now 8 using the length() method
String a = "I love CS";
if (a.equals("I love CS")) {
l = 5; // now l = 5 because the equals() statement was true
}
Method Name | Description | Example |
---|---|---|
int length() |
Returns the number of characters in a string including spaces and punctuation |
"Hi there".length() returns 8 |
String substring(int from, int to) |
Returns a new string that is a piece of the outer string starting from index from and ending at the character before index to . Remember: the first index is 0! |
"Hi there".substring(3,7) returns "ther"
|
int indexOf(String str) |
Searches the outer string for the smaller string str and returns the first index it appears. |
"Hi there".indexOf("the") returns 3
|
boolean equals(String other) |
returns true if the characters in the outer are the same as the characters in other . This will be true even if the strings are at different addresses. |
"Hi there".equals("Hi there") returns true . |
int compareTo(String str) |
returns a positive integer if the outer string comes AFTER str in alphabetical order, and a negative number if the outer string comes BEFORe str in alphabetical order. |
"apple".compareTo("bat") will return a negative number, but "bat".compareTo("apple") will return a positive number |
Note: This is a bit beyond the needed scope of the course, but a deep understanding of what’s happening with strings can be helpful. Don’t worry about memorizing every step of this process.
When you use an equals sign to the right of a variable to set its value, that is called assigning a value to the variable. We can assign literals OR other variables of the same type. In all cases, the value of the assigned element is copied into the assignee.*
1
2
3
4
5
6
7
8
9
int numCookies = 3;
// creates a new int called numCookies in the Variable Lookup Table,
// then copies the value 3 in the value spot
int numCakes = numCookies;
// creates a new int numCakes, copies the value from numCookies to it
// The end result of these two is two different integer values in the table with
// the same value - 3 - but changes to one will not effect the other from now on.
String
s specfically are so common and important that java actually creates a special thing called a String Lookup Table that allows us to save space by only creating a string value one time.
Consider the code below and read the comments to get a sense of how it works. Note that initializing String
s with a literal is significantly more complex than with primitives like int
, but assigning one variable to another is the same level of complexity!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
String firstName = "Douglas";
/* This starts the same - create a spot in the variable
* table called firstName, set its size and type.
* But it gets really different after that because String's are special.
* First, this will use the String Lookup Table to see if there is
* already a string in the heap that has the value "Douglas".
* If there is, it will copy the address of that
* string into the value of the table.
* If there isn't, it will create a new string in the heap with
* that value and copy the address into the table.
*/
String middleName = "Douglas";
/* This will follow the same steps as for firstName,
* but since it finds "Douglas" in the String table,
* it will assign the same address to middleName as firstName
*/
String lastName = firstName;
/* creates a spot in the variable table called lastName
* and copies the value from firstName to lastName.
* Notice that the 'variable = variable' form works
* EXACTLY the same for strings as integers,
* but what is copied is the address, not the value!
* Strings are only special when String *primitives* are involved.
*/
/* The end result of this is that all three variables -
* firstname, middleName, lastName -
* all have the same value in the variable lookup table -
* the address of a spot in the heap
* where a string with that value is stored.
* They are three names for the same thing!
*/