Strings
A String is text — a name, an address, a sentence pulled from a form field. It's technically not a primitive type but a full object, and that one fact explains most of the quirks you'll run into while working with it.
Strings are objects, and objects are immutable here
Once a String is created, it can never be changed. Every method that looks like it's "modifying" a string — toUpperCase(), trim(), replace() — is actually building and returning a brand new String, leaving the original untouched.
String original = "hello"; String shouted = original.toUpperCase(); System.out.println(original); System.out.println(shouted);
hello HELLO
original still says "hello" — calling toUpperCase() didn't touch it, it handed back a separate String that we stored in shouted. If you forget this and write original.toUpperCase(); on its own line expecting original to change, nothing will happen, and there won't be an error to tell you why.
Building and combining strings
The + operator concatenates strings, and Java will automatically convert numbers and booleans to text when they're mixed into a concatenation:
public class Invoice {
public static void main(String[] args) {
String customer = "Dana Whitfield";
int itemCount = 3;
double total = 84.50;
String summary = customer + " ordered " + itemCount + " items, total $" + total;
System.out.println(summary);
}
}
Dana Whitfield ordered 3 items, total $84.5
Notice $84.5, not $84.50 — Java doesn't know this number represents money, so it drops the trailing zero like any other double. Formatting currency properly needs something like String.format("%.2f", total), which is worth knowing exists even before you need the full details of it.
Useful String methods
A String comes with a long list of built-in methods. These four cover the majority of everyday work:
.length()— the number of characters. Note it's a method with parentheses, unlike an array's.lengthfield..charAt(index)— the single character at a position, counting from zero..substring(start, end)— a slice of the string, fromstartup to (but not including)end..indexOf(text)— the position wheretextfirst appears, or-1if it's not found anywhere.
public class EmailParser {
public static void main(String[] args) {
String email = "steve.watson@nutriessential.com";
int atIndex = email.indexOf('@');
String username = email.substring(0, atIndex);
String domain = email.substring(atIndex + 1);
System.out.println("Username: " + username);
System.out.println("Domain: " + domain);
System.out.println("Length: " + email.length());
}
}
Username: steve.watson Domain: nutriessential.com Length: 32
Comparing strings the right way
This is the one habit worth locking in early: use .equals() to compare string content, never ==.
String input = new String("yes");
String target = "yes";
System.out.println(input == target);
System.out.println(input.equals(target));
false true
input and target hold the same text, but new String("yes") forces Java to create a distinct object in memory, so == — which checks whether two variables point at the identical object — says false. .equals() looks at the actual characters instead, and correctly says true. In everyday code you rarely write new String(...) yourself, but the underlying rule always applies: == on any object type, strings included, is an identity check, not a content check.
+ concatenation creates a new String object on every single pass, which gets wasteful fast. StringBuilder exists for exactly that situation: it can grow and change in place, and you call .toString() once at the end to get your finished String back.