Skip to content

Commit dacd106

Browse files
author
Daniel
committed
String examples
1 parent 702db59 commit dacd106

6 files changed

Lines changed: 1409 additions & 9 deletions

File tree

TOPICS_PLAN.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,15 @@ All pattern matching features below are **finalized and production-ready** in Ja
138138

139139
### 7. strings/ - String API
140140

141-
| Status | Example | Concepts |
142-
|--------|---------------------------|-----------------------------------------------------|
143-
| [ ] | StringMethodsExample | isBlank, lines, strip, repeat, indent (Java 11+) |
144-
| [ ] | TextBlockExample | Multi-line strings, escaping, formatting (Java 15+) |
145-
| [ ] | StringImmutabilityExample | Why strings are immutable, string pool |
146-
| [ ] | StringBuilderExample | StringBuilder vs StringBuffer, when to use |
147-
| [ ] | StringFormattingExample | String.format, formatted(), printf |
141+
Core feature for text handling. All methods shown are stable and widely used.
142+
143+
| Status | Example | Concepts |
144+
|--------|-------------------------|--------------------------------------------------------|
145+
| [x] | StringMethodsExample | isBlank, strip, lines, repeat, indent (Java 11+) |
146+
| [x] | TextBlockExample | Multi-line strings, indentation, escapes (Java 15+) |
147+
| [x] | StringBasicsExample | Immutability, string pool, intern(), == vs equals() |
148+
| [x] | StringBuilderExample | Mutable strings, performance, StringJoiner |
149+
| [x] | StringFormattingExample | format(), formatted(), printf, locales, MessageFormat |
148150

149151
---
150152

@@ -195,8 +197,8 @@ Core language feature for error handling. Essential for robust Java applications
195197
| fp | Complete | 6/6 |
196198
| oop | Complete | 6/6 |
197199
| pattern | Complete | 6/6 |
198-
| strings | Not Started | 0/5 |
200+
| strings | Complete | 5/5 |
199201
| generics | Complete | 5/5 |
200202
| exceptions | Complete | 4/4 |
201203
| io | Not Started | 0/3 |
202-
| **Total** | | **55/63** |
204+
| **Total** | | **60/63** |
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
package org.nkcoder.strings;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* String Basics: Immutability, String Pool, and Core Concepts.
7+
*
8+
* <p><strong>Java 25 Status:</strong> Fundamental concepts unchanged. Understanding
9+
* string immutability and the string pool is essential for writing efficient code.
10+
*
11+
* <p>Key concepts:
12+
* <ul>
13+
* <li>String immutability and its benefits</li>
14+
* <li>String pool (interning)</li>
15+
* <li>String comparison: == vs equals()</li>
16+
* <li>Memory considerations</li>
17+
* </ul>
18+
*/
19+
public class StringBasicsExample {
20+
21+
public static void main(String[] args) {
22+
stringImmutability();
23+
stringPool();
24+
equalsVsDoubleEquals();
25+
internMethod();
26+
memoryConsiderations();
27+
commonMistakes();
28+
}
29+
30+
// ===== String Immutability =====
31+
32+
static void stringImmutability() {
33+
System.out.println("=== String Immutability ===");
34+
35+
String original = "Hello";
36+
String modified = original.toUpperCase();
37+
38+
System.out.println(" Original: " + original); // Still "Hello"
39+
System.out.println(" Modified: " + modified); // "HELLO" - new object
40+
41+
// Every "modification" creates a new String
42+
String s = "a";
43+
System.out.println("\n String operations create new objects:");
44+
System.out.println(" s = \"a\"");
45+
System.out.println(" s.concat(\"b\") returns: " + s.concat("b"));
46+
System.out.println(" s is still: " + s);
47+
48+
System.out.println("""
49+
50+
Why immutability matters:
51+
1. Thread Safety - strings can be shared without synchronization
52+
2. Security - string values can't be changed after validation
53+
3. Caching - hashCode can be cached (used in HashMap keys)
54+
4. String Pool - safe to share instances
55+
56+
Consequence:
57+
- String concatenation in loops creates many objects
58+
- Use StringBuilder for building strings dynamically
59+
""");
60+
}
61+
62+
// ===== String Pool (String Interning) =====
63+
64+
static void stringPool() {
65+
System.out.println("=== String Pool ===");
66+
67+
// String literals go to the pool
68+
String a = "Hello";
69+
String b = "Hello";
70+
71+
// Same reference (from pool)
72+
System.out.println(" String a = \"Hello\"");
73+
System.out.println(" String b = \"Hello\"");
74+
System.out.println(" a == b: " + (a == b)); // true - same pool reference
75+
76+
// new String() creates object on heap, not in pool
77+
String c = new String("Hello");
78+
System.out.println("\n String c = new String(\"Hello\")");
79+
System.out.println(" a == c: " + (a == c)); // false - different objects
80+
System.out.println(" a.equals(c): " + a.equals(c)); // true - same content
81+
82+
// Compile-time constant expressions are pooled
83+
String d = "Hel" + "lo"; // Evaluated at compile time
84+
System.out.println("\n String d = \"Hel\" + \"lo\"");
85+
System.out.println(" a == d: " + (a == d)); // true - compiler optimizes
86+
87+
// Runtime concatenation is NOT pooled
88+
String prefix = "Hel";
89+
String e = prefix + "lo"; // Evaluated at runtime
90+
System.out.println("\n String e = prefix + \"lo\" (runtime)");
91+
System.out.println(" a == e: " + (a == e)); // false - heap object
92+
93+
System.out.println();
94+
}
95+
96+
// ===== equals() vs == =====
97+
98+
static void equalsVsDoubleEquals() {
99+
System.out.println("=== equals() vs == ===");
100+
101+
String s1 = "Hello";
102+
String s2 = new String("Hello");
103+
String s3 = "Hello";
104+
105+
System.out.println(" s1 = \"Hello\" (literal)");
106+
System.out.println(" s2 = new String(\"Hello\")");
107+
System.out.println(" s3 = \"Hello\" (literal)");
108+
109+
System.out.println("\n Reference comparison (==):");
110+
System.out.println(" s1 == s2: " + (s1 == s2)); // false
111+
System.out.println(" s1 == s3: " + (s1 == s3)); // true
112+
113+
System.out.println("\n Content comparison (equals):");
114+
System.out.println(" s1.equals(s2): " + s1.equals(s2)); // true
115+
System.out.println(" s1.equals(s3): " + s1.equals(s3)); // true
116+
117+
// Null-safe comparison
118+
String nullStr = null;
119+
// nullStr.equals(s1); // NullPointerException!
120+
System.out.println("\n Null-safe patterns:");
121+
System.out.println(" \"Hello\".equals(nullStr): " + "Hello".equals(nullStr));
122+
System.out.println(" Objects.equals(nullStr, s1): " +
123+
Objects.equals(nullStr, s1));
124+
125+
System.out.println("""
126+
127+
RULE: Always use equals() for String comparison
128+
- == compares references (memory addresses)
129+
- equals() compares content
130+
- Only use == to check for null
131+
""");
132+
}
133+
134+
// ===== intern() Method =====
135+
136+
static void internMethod() {
137+
System.out.println("=== intern() Method ===");
138+
139+
String a = "Hello";
140+
String b = new String("Hello");
141+
String c = b.intern(); // Get pooled version
142+
143+
System.out.println(" a = \"Hello\" (literal, in pool)");
144+
System.out.println(" b = new String(\"Hello\") (heap)");
145+
System.out.println(" c = b.intern() (get pool reference)");
146+
147+
System.out.println("\n a == b: " + (a == b)); // false
148+
System.out.println(" a == c: " + (a == c)); // true - c points to pool
149+
150+
System.out.println("""
151+
152+
intern() behavior:
153+
- If string exists in pool, returns pool reference
154+
- If not, adds to pool and returns new reference
155+
- Use sparingly - pool has limited size
156+
157+
When to use intern():
158+
- Processing many duplicate strings (e.g., XML parsing)
159+
- Memory optimization for repeated values
160+
- Generally: let JVM handle it (literals auto-interned)
161+
""");
162+
}
163+
164+
// ===== Memory Considerations =====
165+
166+
static void memoryConsiderations() {
167+
System.out.println("=== Memory Considerations ===");
168+
169+
// Substring behavior (Java 7+)
170+
String large = "A".repeat(10000);
171+
String small = large.substring(0, 10);
172+
173+
// In Java 7+, substring creates NEW char array (no memory leak)
174+
System.out.println(" large.length(): " + large.length());
175+
System.out.println(" small.length(): " + small.length());
176+
System.out.println(" small: " + small);
177+
178+
// String memory: header + char array reference + hash + char[]
179+
// char[] uses 2 bytes per character (UTF-16)
180+
// Compact strings (Java 9+): Latin-1 strings use 1 byte per char
181+
182+
System.out.println("""
183+
184+
Memory facts:
185+
- Each String object: ~40+ bytes overhead
186+
- Character storage: 1 byte (Latin-1) or 2 bytes (UTF-16)
187+
- Java 9+ Compact Strings: auto-detects encoding
188+
- Substring: creates new String (no shared backing array)
189+
190+
Optimizations:
191+
- String pool reduces duplicates
192+
- Compact strings save ~50% for ASCII
193+
- StringBuilder for concatenation in loops
194+
""");
195+
}
196+
197+
// ===== Common Mistakes =====
198+
199+
static void commonMistakes() {
200+
System.out.println("=== Common Mistakes ===");
201+
202+
// Mistake 1: Using == for comparison
203+
System.out.println(" Mistake 1: Using == instead of equals()");
204+
String input = new String("yes");
205+
// BAD: if (input == "yes") // Might fail!
206+
// GOOD:
207+
if ("yes".equals(input)) {
208+
System.out.println(" Correct: \"yes\".equals(input)");
209+
}
210+
211+
// Mistake 2: String concatenation in loops
212+
System.out.println("\n Mistake 2: Concatenation in loops");
213+
System.out.println("""
214+
BAD:
215+
String result = "";
216+
for (...) { result += item; } // Creates many String objects
217+
218+
GOOD:
219+
StringBuilder sb = new StringBuilder();
220+
for (...) { sb.append(item); }
221+
String result = sb.toString();
222+
""");
223+
224+
// Mistake 3: Not handling null
225+
System.out.println(" Mistake 3: NullPointerException");
226+
System.out.println("""
227+
BAD:
228+
if (userInput.equals("expected")) // NPE if userInput is null
229+
230+
GOOD:
231+
if ("expected".equals(userInput)) // Safe
232+
if (Objects.equals(userInput, "expected")) // Also safe
233+
""");
234+
235+
// Mistake 4: Forgetting immutability
236+
System.out.println(" Mistake 4: Forgetting immutability");
237+
String s = "hello";
238+
s.toUpperCase(); // Does nothing! Return value ignored
239+
System.out.println(" After s.toUpperCase(): " + s); // Still "hello"
240+
s = s.toUpperCase(); // Must reassign
241+
System.out.println(" After s = s.toUpperCase(): " + s);
242+
243+
System.out.println();
244+
}
245+
}

0 commit comments

Comments
 (0)