String is an object, not a primitive
Almost everything real programs handle is text: usernames, file paths, URLs, JSON from an API. In Java all of it lives in String (capital S, double quotes). Unlike the primitives from lesson 2-1, a String is an object: a bundle of data plus methods you call with a dot, just like Python's "abc".upper().
String lang = "Java"; lang.length() // 4 lang.toUpperCase() // "JAVA" lang.charAt(0) // 'J' (a char) lang.substring(1) // "ava" (from index 1 to end) lang.contains("av") // true
Strings are immutable, same as Python: methods return a new String and never change the original.
Code exercise · java
Run this tour of the core String methods. Notice that lang itself is unchanged at the end.
The == trap
For primitives, == compares values and works as expected. For objects, == asks "are these the same object in memory?", not "do they look equal?". To compare String contents, always use .equals(...):
String a = "hi"; String b = new String("hi"); a == b // false! different objects a.equals(b) // true, same characters
This is the single most common beginner bug in Java. Rule: == for primitives, .equals() for objects.
The behavior follows from where Java stores things. Local variables live on the stack, a small fast memory region tied to the method currently running. Objects live on the heap, a larger region for data that can outlive any single method. A variable of object type holds only a reference — the heap location of the object — so == on two object variables compares the two locations, not the characters stored at them. The diagram below shows exactly that.
Quiz
Two String variables a and b were built separately but contain the same characters. Which comparison reliably answers "do they hold the same text"?
Code exercise · java
Your turn. Given the word already declared, print four lines: its length, its first character, its last character, and the whole word in uppercase.