Chapter 4 โ Core APIs
Key Topics: String immutability, concatenation rules, core String methods (indexing, substring, search, replacement, strip/trim, indent, isEmpty/isBlank, formatting), method chaining, StringBuilder mutability, capacities, common StringBuilder methods, String pool internals & interning, arrays (primitives vs. objects, bracket declarations, anonymous arrays), Arrays utility (sorting, binary search index calculation, compare, mismatch), varargs, multidimensional arrays, Math API, BigInteger/BigDecimal, Date-Time API (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant), ChronoUnit, Period vs. Duration, Daylight Saving Time (DST) arithmetic.
๐ฆ New Learner: Core API Basicsโ
Strings & Concatenationโ
A String is an immutable sequence of characters. It implements CharSequence and does not require the new keyword to instantiate.
Concatenation Rules:โ
- If both operands are numeric,
+performs numeric addition. - If either operand is a
String,+performs string concatenation. - Expressions are evaluated strictly from left to right.
System.out.println(1 + 2); // 3
System.out.println("a" + "b" + 3); // ab3
System.out.println(1 + 2 + "c"); // 3c (1 + 2 evaluated first -> 3 + "c")
System.out.println("c" + 1 + 2); // c12 ("c" + 1 -> "c1" + 2 -> "c12")
System.out.println("c" + null); // cnull
Essential String Methodsโ
Java uses 0-based indexing for characters in a string.
length(): Returns the number of characters in the string.var name = "animals";System.out.println(name.length()); // 7 (normal counting)charAt(int index): Returns the character at the specified index. ThrowsStringIndexOutOfBoundsExceptionif index is out of bounds.System.out.println(name.charAt(0)); // aSystem.out.println(name.charAt(7)); // โ Throws ExceptionindexOf(): Finds the first index matching a character or substring. Returns-1if no match is found (never throws exceptions).System.out.println(name.indexOf('a')); // 0System.out.println(name.indexOf("al")); // 4System.out.println(name.indexOf('a', 4)); // 4 (starts search at index 4)System.out.println(name.indexOf('a', 2, 4));// -1 (search between index 2 [inclusive] and 4 [exclusive])substring(int beginIndex, int endIndex): Returns a substring starting atbeginIndex(inclusive) and stopping right beforeendIndex(exclusive).System.out.println(name.substring(3)); // mals (goes to the end)System.out.println(name.substring(3, 4)); // mSystem.out.println(name.substring(3, 7)); // mals (7 is the end of the string, valid boundary)System.out.println(name.substring(3, 3)); // "" (empty string)System.out.println(name.substring(3, 2)); // โ Throws StringIndexOutOfBoundsException (backward indices)replace(char old, char new): Returns a new string with replaced characters/substrings.System.out.println("abcabc".replace('a', 'A')); // AbcAbctrim()/strip(): Removes leading and trailing whitespace.strip()is preferred in modern Java as it supports Unicode whitespace.stripLeading(): Removes leading whitespace only.stripTrailing(): Removes trailing whitespace only.
isEmpty()vsisBlank():isEmpty()returnstrueonly iflength() == 0.isBlank()returnstrueif empty or containing only whitespace.
System.out.println(" ".isEmpty()); // falseSystem.out.println(" ".isBlank()); // true
String Formattingโ
Use String.format() or formatted() to build formatted strings.
var name = "Kate";
var order = 5;
// Both evaluate to: "Hello Kate, order 5 is ready"
String s1 = String.format("Hello %s, order %d is ready", name, order);
String s2 = "Hello %s, order %d is ready".formatted(name, order);
Formatting Symbols:โ
%s: Any type (typically formats as String via.toString()).%d: Integer types (int,long,byte,short).%f: Floating-point types (float,double).%n: System-dependent line break.
Passing a float type to %d causes an IllegalFormatConversionException at runtime:
var s = "Score: %d".formatted(95.5); // โ Throws Exception
Mutability & StringBuilderโ
Since String is immutable, frequent concatenation creates many garbage objects. StringBuilder is a mutable alternative.
StringBuilder sb = new StringBuilder("start");
sb.append("+middle"); // Modifies sb directly
StringBuilder same = sb.append("+end"); // returns a reference to itself
System.out.println(sb == same); // true (point to the same object!)
Constructors:โ
StringBuilder sb1 = new StringBuilder(); // Empty sequence, default capacity (16)
StringBuilder sb2 = new StringBuilder("animal");// Specific string value
StringBuilder sb3 = new StringBuilder(10); // Empty sequence, specific initial capacity
StringBuilder Methods:โ
append(val): Appends various data types to the end.insert(int offset, val): Inserts data starting at indexoffset.var sb = new StringBuilder("animals");sb.insert(7, "-"); // animals-sb.insert(0, "-"); // -animals-sb.insert(4, "-"); // -ani-mals-delete(int start, int end)&deleteCharAt(int index): Removes characters betweenstart(inclusive) andend(exclusive).replace(int start, int end, String newStr): Deletes elements fromstarttoend, then insertsnewStratstart.reverse(): Reverses the character sequence.
Primitives vs. Object Equalityโ
==compares primitive values or object reference addresses.equals()performs logical comparison based on object class implementations.
var sb1 = new StringBuilder("a");
var sb2 = new StringBuilder("a");
System.out.println(sb1.equals(sb2)); // false (uses default reference comparison!)
// Correct way:
System.out.println(sb1.toString().equals(sb2.toString())); // true
Array Fundamentalsโ
An array is a fixed-size heap object containing contiguous slots for primitives or object references.
Declarations & Bracket Positions:โ
int[] ids, types; // Two int[] arrays
int ids2[], types2; // ids2 is an int[] array, types2 is a single int variable!
Initialization:โ
int[] numbers = new int[3]; // [0, 0, 0] (initialized to primitive default values)
int[] numbers2 = new int[] {42, 55, 99}; // Initialized with specific values
int[] numbers3 = {42, 55, 99}; // Anonymous array shortcut
Elements and length:โ
- Use
.length(a property, not a method) to find capacity. - Valid index range is
0tolength - 1. Out of range indices throwArrayIndexOutOfBoundsException.
๐ฃ Senior Deep Diveโ
String Pool and Interningโ
To save memory, the JVM stores compile-time string literals and constants in the String Pool.
[ STACK ] [ HEAP ]
+---------------------+ +------------------------+
| x: reference ------+-----------> "Hello World" (Pool) |
| y: reference ------+----------/ |
| z: reference ------+-----------> "Hello World" (Object) |
+---------------------+ +------------------------+
var x = "Hello World";
var y = "Hello World";
System.out.println(x == y); // true (Literal references point to String Pool)
var z = new String("Hello World");
System.out.println(x == z); // false (new forces a distinct heap object)
// Interning: force reference to pool
var internedZ = z.intern();
System.out.println(x == internedZ); // true
Compile-Time Constants vs Runtime Computations:โ
var first = "rat" + 1; // Compile-time constant -> pooled "rat1"
var second = "r" + "a" + "t" + "1"; // Compile-time constant -> pooled "rat1"
var third = "r" + "a" + "t" + new String("1"); // Runtime computed -> new heap object
System.out.println(first == second); // true
System.out.println(first == third); // false
Arrays Utility Class (java.util.Arrays)โ
Sorting (7Up Rule)โ
Arrays.sort() sorts elements in natural order: Numbers (7) -> Uppercase letters (U) -> Lowercase letters (p).
String[] strings = { "10", "9", "100" };
Arrays.sort(strings); // Alphabetical: ["10", "100", "9"]
Binary Searchโ
Arrays.binarySearch(array, target) requires a sorted array.
- If found: Returns the index of the match.
- If not found: Returns
-(insertionPoint) - 1(showing where the element should be inserted to keep the array sorted).
int[] numbers = {2, 4, 6, 8};
System.out.println(Arrays.binarySearch(numbers, 2)); // 0
System.out.println(Arrays.binarySearch(numbers, 3)); // -2 (should insert at index 1 -> -1 - 1 = -2)
System.out.println(Arrays.binarySearch(numbers, 9)); // -5 (should insert at index 4 -> -4 - 1 = -5)
Comparison APIs:โ
Arrays.compare(a, b): Returns a negative number ifa < b,0ifa == b, and positive ifa > b.nullis smaller than any other value.- If one array is a prefix of another, the shorter array is smaller.
Arrays.mismatch(a, b): Returns the first index where the arrays differ, or-1if they are equal.
System.out.println(Arrays.mismatch(new int[]{1, 2}, new int[]{1})); // 1 (index of difference)
Multidimensional Arraysโ
Java supports arrays of arrays (multidimensional arrays), which can be rectangular or asymmetric (jagged).
int[][] args1 = new int[2][]; // First dimension initialized, second is null
args1[0] = new int[5]; // Jagged array construction
args1[1] = new int[3];
// Iterating asymmetric array
for (int[] inner : args1) {
for (int num : inner) {
System.out.print(num + " ");
}
}
Math APIsโ
Math.max(a, b)/Math.min(a, b): Overloaded forint,long,float,double.Math.round(num): Rounds half up. Returnslongfordoubleinput, andintforfloatinput.Math.ceil(double): Rounds up to the next integer (returnsdouble).Math.floor(double): Rounds down (returnsdouble).Math.pow(double base, double exp): Returnsbase^{exp}as adouble.Math.random(): Returns adoublein range[0.0, 1.0).
BigInteger and BigDecimalโ
Used for infinite-precision math. Unlike primitives, they are immutable objects.
- Use
valueOf()or constructor to initialize. - Use
.add(),.subtract(),.multiply(),.divide(). BigDecimalprevents floating-point rounding errors:
double errorVal = 64.1 * 100; // 6409.999999999999
BigDecimal correctVal = BigDecimal.valueOf(64.1).multiply(BigDecimal.valueOf(100)); // 6410.0
Date-Time APIs (java.time.*)โ
Java 8 introduced modern date-time classes with private constructors (Factory Pattern). Use .of() or .now().
| Class | Contains | Format Example |
|---|---|---|
LocalDate | Date only | 2025-01-20 |
LocalTime | Time only | 06:15:30.200 |
LocalDateTime | Date + Time | 2025-01-20T06:15:30.200 |
ZonedDateTime | Date + Time + Time Zone | 2025-01-20T06:15:30.200-05:00[America/New_York] |
Instant | Instant in UTC (GMT) | 2025-01-20T11:15:30Z |
Calling a constructor triggers a compilation error:
var d = new LocalDate(); // โ DOES NOT COMPILE (private constructor)
Periods and Durationsโ
Period: Represents date intervals (Years, Months, Weeks, Days). Format:P1Y2M3D.Duration: Represents time intervals (Days, Hours, Minutes, Seconds, Nanos). Format:PT2H30M.
var date = LocalDate.of(2025, 1, 20);
var period = Period.ofMonths(1);
System.out.println(date.plus(period)); // 2025-02-20
var time = LocalTime.of(6, 15);
var duration = Duration.ofHours(6);
System.out.println(time.plus(duration)); // 12:15
System.out.println(date.plus(duration)); // โ Throws UnsupportedTemporalTypeException (no time fields in LocalDate)
You cannot chain static creation methods in Period or Duration. Only the last call is evaluated:
var p = Period.ofYears(1).ofWeeks(1); // โ Warns/Evaluates to Period.ofWeeks(1) ONLY!
// Correct way:
var pCorrect = Period.of(1, 0, 7); // 1 year, 0 months, 7 days
ChronoUnit and Instantsโ
- Use
ChronoUnitto calculate difference between temporal objects:long mins = ChronoUnit.MINUTES.between(time1, time2); Instantrepresents a moment in UTC. Convert viaZonedDateTime.toInstant(). You cannot convertLocalDateTimetoInstantdirectly without a zone offset.
Daylight Saving Time (DST)โ
The U.S. clock change occurs at 2:00 a.m. early Sunday morning.
- Spring Forward (March): Clocks jump from 1:59 a.m. to 3:00 a.m. The hour between 2:00 and 2:59 does not exist.
- Fall Back (November): Clocks jump from 1:59 a.m. back to 1:00 a.m. The hour between 1:00 and 1:59 is repeated twice.
// Spring Forward Example:
var date = LocalDate.of(2025, Month.MARCH, 9);
var time = LocalTime.of(1, 30);
var zone = ZoneId.of("US/Eastern");
var dt = ZonedDateTime.of(date, time, zone); // 2025-03-09T01:30-05:00
dt = dt.plusHours(1); // Springs forward over 2:00 a.m.
System.out.println(dt); // 2025-03-09T03:30-04:00 (Notice time and offset change!)
๐ Exam Quick Referenceโ
Rules & Restrictions Summaryโ
| Topic | Critical Fact |
|---|---|
| String pool | Holds string literals and constants. Created on the heap. |
substring(a, b) | Starts at a, ends at b-1. If a == b, returns "". Throws if b < a. |
indexOf() | Returns -1 if not found. Starting index parameter is inclusive. |
trim() vs strip() | strip() is Unicode-aware; trim() only handles ASCII <= space character. |
StringBuilder mutability | Methods like append(), insert(), delete() modify the object in-place and return a reference. |
| Array declarations | Space and bracket ordering options exist. int ids[] vs int[] ids. |
binarySearch() | Must be sorted first. Insertion point formula: -(index) - 1. |
Arrays.compare() | Negative if first is smaller, 0 if equal, positive if larger. null is smallest. |
| Date/Time class math | Modern dates are immutable. You must assign the result of .plus()/.minus(). |
| Period parameters | Period handles only years, months, and days. Duration handles days, hours, minutes, seconds, nanos. |
| Daylight Saving Time | Skipping/repeating hours occurs depending on March/November shifts. |
๐จ Extra Exam Tipsโ
Trap 1 โ Ignoring date/time return values:
var date = LocalDate.of(2025, 1, 20);
date.plusDays(10); // Return value ignored!
System.out.println(date); // prints 2025-01-20
Trap 2 โ Unsupported Date-Time operations:
var date = LocalDate.of(2025, 1, 20);
date.plusMinutes(5); // โ DOES NOT COMPILE (LocalDate has no time fields)
Trap 3 โ Comparing mismatched types:
String s = "a";
StringBuilder sb = new StringBuilder("a");
System.out.println(s == sb); // โ DOES NOT COMPILE (types are incompatible)
Trap 4 โ Binary search on unsorted arrays:
int[] nums = {3, 2, 1};
System.out.println(Arrays.binarySearch(nums, 2)); // Result is undefined/unpredictable!
Trap 5 โ Array length property vs String length method:
int[] arr = new int[5];
System.out.println(arr.length); // property (no parentheses)
String s = "abc";
System.out.println(s.length()); // method (has parentheses)
Trap 6 โ String Pool comparison vs. runtime concatenation:
String s1 = "rat1";
String s2 = "rat" + new String("1");
System.out.println(s1 == s2); // false (computed at runtime, not pooled)
Trap 7 โ Invalid index limits in substring():
String s = "abc";
s.substring(1, 4); // โ Throws StringIndexOutOfBoundsException (max endIndex is length() = 3)
Trap 8 โ ArrayStoreException at runtime:
Object[] objs = new String[1];
objs[0] = new StringBuilder(); // Compiles, but throws ArrayStoreException at runtime!
Trap 9 โ Rounding method return types:
int val = Math.round(3.14); // โ DOES NOT COMPILE: Math.round(double) returns a long!
Trap 10 โ Invalid Period / Duration arguments:
Period.of(1, 2, 3, 4); // โ DOES NOT COMPILE: Period.of() accepts at most 3 parameters (years, months, days)
Exam Vignettesโ
// Vignette: StringBuilder offset insertion
StringBuilder sb = new StringBuilder("123");
sb.append("45").insert(2, "-");
// 1. sb.append("45") -> "12345"
// 2. sb.insert(2, "-") -> inserts '-' at index 2 -> "12-345"
BigDecimalin Financial Services: Never usedoublefor currency calculations in Spring transactional services. UseBigDecimalto prevent precision loss.- Date conversions in Spring APIs: Spring Boot uses Jackson to serialize Date-Time objects. Correctly formatting
ZonedDateTimeensures timezones are preserved across microservice boundaries.
๐ Review Questions Focusโ
- Immutable assignments: Recognize ignored math operations on
LocalDate/String. - Binary search outcomes: Predict values returned when items are not present in a sorted array.
- Capacity declarations: Differentiate
new StringBuilder(10)capacity allocation from actual character length. - Daylight Saving offsets: Track timezone offset modifications during spring-forward and fall-back weekends.
- Array comparison rules: Compare sorting criteria (7Up) in
Arrays.compare(). - Varargs arrays: Treat
String... argsparameters as arrays inside method blocks. - Math return types: Recognize when
Mathmethods returndoublevs.longorint. - String Pool allocations: Differentiate
intern()matches from runtime string concatenations. - Jagged array iterations: Trace loops on asymmetric multidimensional structures.
- Exception types: Identify runtime errors like
ArrayStoreExceptionandUnsupportedTemporalTypeException.