Theory
The search that worked only in the lab
BookBridge gets a title search. You test it:
if (typed == b.title) ...
In the lab it finds "Let Us C" perfectly. Demo day: the librarian types the exact same title, and the search returns nothing. Same spelling, same case, you print both strings and they look identical.
Nothing is wrong with her typing. Something is wrong with ==, and the reason it fooled you is one of Java's favourite interview questions.
Theory
String is a class with a warehouse
A Java String is an object, not a primitive: title holds a reference to character data, just like Book b holds a reference to a Book.
Java adds one optimisation: the string pool. Every string literal in your code goes into a shared warehouse, and identical literals reuse one pooled object. So 2 variables assigned "Let Us C" point to the same object.
But strings built at run time (user input, concatenation, new String(...)) live outside the pool as fresh objects.
Practical
Same characters, different objects
public class TitleCheck {
public static void main(String[] args) {
String a = "Let Us C"; // literal: pooled
String b = "Let Us C"; // same pooled object as a
String c = new String("Let Us C"); // forced NEW object
System.out.println(a == b); // true: same object
System.out.println(a == c); // false: different objects
System.out.println(a.equals(c)); // true: same characters
}
}
Theory
== asks where, equals asks what
== between objects compares references: do these 2 variables point at the same object in memory?
.equals() compares content: do these strings hold the same characters?
That solves the mystery: your test compared 2 literals, both drawn from the pool, same object, == true by luck. The librarian's typed title arrived as a fresh runtime object: same characters, different address, == false.
Relatives worth knowing: equalsIgnoreCase("let us c"), and compareTo for dictionary order (0 means equal).
Quiz
String s = "book"; s.concat("bridge"); System.out.println(s); What prints?
- book
- bookbridge
- bridge
- Compile error: Strings cannot be concatenated by a method
Show the answer
book
Strings are immutable: concat cannot change s; it builds and RETURNS a new String, which this code throws away by not assigning it. s still points at "book". To keep the result you must write s = s.concat("bridge"). Option B is the trap for students who assume in-place modification, which is how the mutable StringBuffer behaves, 2 lessons from now. Nothing here fails to compile; the code is legal, just useless.
Think first
Immutable, so what happens on +?
If no String can ever change, what does title + " (2nd Ed)" actually do to memory? Reason it out before tapping.
Show the answer
It creates a third, brand-new String holding the joined characters; both originals stay untouched. Every + on strings makes a new object. That is harmless for a few joins, but building a 6000-line catalog by looping s = s + line creates thousands of throwaway objects; Java's answer to that cost is StringBuffer, arriving 2 lessons ahead. Bonus thread: BCA204's Python strings were immutable for the same reasons: safe sharing and pooling.
Watch out
The rule that saves the demo
Never compare string content with ==. It works exactly often enough (pooled literals) to survive your testing and fail in front of the client.
Also watch the null direction: if typed might be null, typed.equals(a) throws a NullPointerException; the defensive habit is "Let Us C".equals(typed), literal first, which is simply false when typed is null.
Theory
What this buys BookBridge
The fixed search is one line: if (typed.equals(b.title)), case-insensitive if the librarian prefers: equalsIgnoreCase. Immutability, the second idea of this lesson, is not an inconvenience; it is why Strings are safe to share between objects and threads (Unit 4) without anyone corrupting your titles. Next lesson tours the String toolbox: 11 methods that slice, search and clean the librarian's messy input.
Summary
Key takeaways
- String is a class; variables hold references to string objects.
- Identical literals share one pooled object; runtime strings (input, new String) are separate objects.
- == compares references (same object?); .equals() compares characters (same content?).
- Always use .equals() / equalsIgnoreCase for content; compareTo for ordering.
- Strings are immutable: concat and + return new Strings, originals never change.
- s.concat("x") without assignment changes nothing.
- Memory hook: == asks where, equals asks what.