Wrapper Classes, String, StringBuffer, StringBuilder, and Utility Classes in Java
Wrapper Classes
Overview
Wrapper classes provide a way to use primitive data types as objects. For each primitive type, there is a corresponding wrapper class in the java.lang package.
- Purpose: To convert primitive types (
int,char,double, etc.) into reference types (objects) so they can be used in contexts requiring objects, such as collections (ArrayList,HashMap). - Feature: Being objects, they have methods and fields that can be utilized.
- Hierarchy: Wrapper classes extend
Number(for numeric types) orObject.
Conversion between Primitives and Wrapper Classes
Manual Boxing and Unboxing (Before JDK 5)
- Boxing: Converting a primitive to its corresponding wrapper object.
- Unboxing: Converting a wrapper object back to its primitive.
Auto-boxing and Auto-unboxing (JDK 5 onwards)
- Java automatically handles the conversion. Auto-boxing uses the
valueOf()method internally (e.g.,Integer.valueOf()).
public class WrapperConversion {
public static void main(String[] args) {
// Manual boxing & unboxing (pre-JDK 5)
int n1 = 100;
Integer integer1 = new Integer(n1);
Integer integer2 = Integer.valueOf(n1);
int i1 = integer1.intValue();
// Auto-boxing & auto-unboxing (JDK 5+)
int n2 = 200;
Integer integer3 = n2; // Auto-boxing: Integer.valueOf(n2)
int i2 = integer3; // Auto-unboxing: integer3.intValue()
}
}
Conversion between Wrapper and String
public class WrapperAndString {
public static void main(String[] args) {
Integer num = 100;
// Wrapper to String
String str1 = num + ""; // Method 1
String str2 = num.toString(); // Method 2
String str3 = String.valueOf(num); // Method 3
// String to Wrapper
String str4 = "12345";
Integer num2 = Integer.parseInt(str4); // Auto-boxing
Integer num3 = new Integer(str4); // Constructor
}
}
Common Methods of Integer and Character Classes
public class WrapperMethods {
public static void main(String[] args) {
System.out.println(Integer.MIN_VALUE); // Minimum int value
System.out.println(Integer.MAX_VALUE); // Maximum int value
System.out.println(Character.isDigit('a')); // false
System.out.println(Character.isLetter('a')); // true
System.out.println(Character.isUpperCase('a')); // false
System.out.println(Character.isLowerCase('a')); // true
System.out.println(Character.isWhitespace(' ')); // true
System.out.println(Character.toUpperCase('a')); // 'A'
System.out.println(Character.toLowerCase('A')); // 'a'
}
}
String Class
Core Concepts
Stringrepresents a sequence of characters.- String literals are enclosed in double quotes, e.g.,
"hello". - Characters in a
Stringare stored using Unicode, each character (letter or Chinese) occupies two bytes. Stringis immutable. Once created, its value cannot be changed. Any modification creates a new string.Stringisfinaland cannot be subclassed.- It implements
Serializable(for network transmission) andComparable(for comparison).
Constructors
String s1 = new String();String s2 = new String("original");String s3 = new String(char[] a);String s4 = new String(char[] a, int startIndex, int count);String s5 = new String(byte[] b);
Two Ways to Create String Objects
Method 1: Direct Assignment
String s1 = "hello";
- JVM checks the String Constant Pool.
- If the string exists,
s1directly references it. - If not, a new string is created in the pool and referenced.
Method 2: Using new
String s2 = new String("hello");
- A new object is created on the heap.
- Inside this object, a
valueattribute points to the string in the constant pool. s2holds the heap memory address.
Immutability
- Once a
Stringobject is created, its content cannot be changed. - Example:
String s = "hello"; s = "haha";creates two objects:"hello"and"haha".
Common String Methods
| Method | Description |
|---|---|
equals() |
Compares content (case-sensitive). |
equalsIgnoreCase() |
Compares content (case-insensitive). |
length() |
Returns the number of characters. |
indexOf(String str) |
Returns first occurrence index; -1 if not found. |
lastIndexOf(String str) |
Returns last occurrence index; -1 if not found. |
substring(int begin, int end) |
Extracts a substring. |
trim() |
Removes leading and trailing spaces. |
charAt(int index) |
Returns character at specified index. |
toUpperCase() |
Converts to uppercase. |
toLowerCase() |
Converts to lowercase. |
concat(String str) |
Concatenates strings. |
replace(char old, char new) |
Replaces characters. |
split(String regex) |
Splits string into array; may need escape for special chars like | etc. |
compareTo(String another) |
Compares lexicographically. |
toCharArray() |
Converts to a character array. |
format(String format, Object... args) |
Formats strings. %s for string, %c for char, %d for integer, %.2f for float. |
StringBuffer Class
Key Features
- Represents a mutable sequence of characters.
- It is a container that can be modified (append, insert, delete, replace) without creating new objects.
- Thread-safe (synchronized methods), making it suitable for multithreaded environments.
- It is a
finalclass and cannot be inherited. - Internally stores characters in a
char[] valuearray located on the heap.
String vs StringBuffer
| Aspect | String | StringBuffer |
|---|---|---|
| Mutability | Immutable (content never changes) | Mutable (content can be modified) |
| Storage | Strings stored in constant pool; literal reuse possible | Character array stored in heap |
| Performance | Lower due to constant object creation | Higher for frequent modifications |
| Thread Safety | Thread-safe (immutable objects are inherently safe) | Thread-safe (synchronized methods) |
| Usage | Suitable for stable, rarely changed strings | Suitable for frequent modifications in multithreaded scenarios |
Conversion between String and StringBuffer
public class StringAndStringBufferConversion {
public static void main(String[] args) {
String str = "hello";
// String -> StringBuffer
StringBuffer sb1 = new StringBuffer(str); // Constructor
StringBuffer sb2 = new StringBuffer().append(str); // Append method
// StringBuffer -> String
StringBuffer sb3 = new StringBuffer("world");
String s1 = sb3.toString(); // toString method
String s2 = new String(sb3); // String constructor
}
}
Common Methods of StringBuffer
public class StringBufferMethods {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("hello");
// Append
sb.append(',');
sb.append("Alice");
sb.append("Bob").append(100).append(true).append(10.5);
System.out.println(sb); // "hello,AliceBob100true10.5"
// Delete
sb.delete(11, 14); // Deletes characters at indices [11, 14)
System.out.println(sb); // "hello,AliceBob true10.5"
// Replace
sb.replace(9, 11, "Charlie"); // Replaces characters at [9, 11)
System.out.println(sb); // "hello,AliceCharlie true10.5"
// IndexOf
int idx = sb.indexOf("Alice");
System.out.println(idx); // 6
// Insert
sb.insert(9, "David");
System.out.println(sb); // "hello,AliceDavidCharlie true10.5"
// Length
System.out.println(sb.length()); // 27
}
}
StringBuilder Class
Key Features
- Mutable sequence of characters similar to
StringBuffer. - Not thread-safe (non-synchronized methods).
- Designed as a drop-in replacement for
StringBufferin single-threaded environments. - Operates faster than
StringBuffer. - Main methods:
appendandinsert(overloaded for all primitive types).
Comparison: String, StringBuffer, StringBuilder
| Feature | String | StringBuffer | StringBuilder |
|---|---|---|---|
| Mutability | Immutable | Mutable | Mutable |
| Performance | Low (many temporary objects) | High | Highest |
| Thread Safety | Safe (immutable) | Safe (synchronized) | Not safe |
| Recommended Use | Rarely changed strings (e.g., config info) | Frequent modifications in multithreaded context | Frequent modifications in single-thredaed context |
Important Note: Avoid using String for heavy modification in loops. Prefer StringBuffer or StringBuilder for such operations to prevent performance degradation.
Math Class
- Contains static methods for basic math operations: exponentiation, logarithms, square roots, trigonometry, etc.
Arrays Class
toString(): Returns string representation of an array.sort(): Sorts array (natural order or with customComparator).binarySearch(): Performs binary search on a sorted array.copyOf(): Copies a specified range of array elements.fill(): Fills all elements of an array with a specified value.equals(): Compares two arrays for equality of content.asList(): Converts a sequence of values to aList. This returns a fixed-size list backed by the array.
import java.util.Arrays;
import java.util.List;
public class ArraysExample {
public static void main(String[] args) {
Integer[] arr = {1, -1, 7, 0, 89};
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
int index = Arrays.binarySearch(arr, 7);
System.out.println("Index of 7: " + index);
Integer[] newArr = Arrays.copyOf(arr, arr.length);
System.out.println(Arrays.toString(newArr));
Integer[] num = {9, 3, 2};
Arrays.fill(num, 99);
System.out.println(Arrays.toString(num));
Integer[] arr2 = {1, -1, 7, 0, 89};
boolean eq = Arrays.equals(arr, arr2);
System.out.println("Arrays equal: " + eq);
List<Integer> list = Arrays.asList(2, 3, 4, 5, 6, 1);
System.out.println("List from array: " + list);
}
}
System Class
exit(int status): Terminates the JVM.arraycopy(Object src, int srcPos, Object dest, int destPos, int length): Copies elements from source array to destination. Typically used at low level;Arrays.copyOf()is preferred for general use.currentTimeMillis(): Returns current time in milliseconds since epoch (1970-01-01).gc(): Runs the garbage collector.
public class SystemExample {
public static void main(String[] args) {
int[] src = {1, 2, 3};
int[] dest = new int[3];
System.arraycopy(src, 0, dest, 0, 3);
// dest now contains {1, 2, 3}
System.out.println("Current time millis: " + System.currentTimeMillis());
System.gc(); // Suggest garbage collection
}
}
BigInteger and BigDecimal Classes
BigInteger
- Used for handling arbitrarily large integers beyond
longcapacity. - Provides methods for arithmetic operations (
add,subtract,multiply,divide), comparison, etc.
BigDecimal
- Used for high-precision floating-point arithmetic to avoid
doubleprecision loss. - Supports rounding modes (e.g.,
ROUND_CEILING).
import java.math.BigInteger;
import java.math.BigDecimal;
public class BigNumberExample {
public static void main(String[] args) {
BigInteger big1 = new BigInteger("23788888899999999999999999999");
BigInteger big2 = new BigInteger("10099999999999999999999999999999999999999999999999999999999999999999999999999999999");
System.out.println("Addition: " + big1.add(big2));
System.out.println("Subtraction: " + big1.subtract(big2));
System.out.println("Multiplication: " + big1.multiply(big2));
System.out.println("Division: " + big1.divide(big2));
BigDecimal bd1 = new BigDecimal("1999.11");
BigDecimal bd2 = new BigDecimal("3");
System.out.println("Addition: " + bd1.add(bd2));
System.out.println("Subtraction: " + bd1.subtract(bd2));
System.out.println("Multiplication: " + bd1.multiply(bd2));
// Division may throw ArithmeticException for non-terminating decimal expansions; use rounding
System.out.println("Division with rounding: " + bd1.divide(bd2, BigDecimal.ROUND_CEILING));
}
}
Date and Time Classes
First Generation: java.util.Date and SimpleDateFormat
Date: Represents a specific instant in time, accurate to milliseconds.SimpleDateFormat: For formatting (Date to String) and parsing (String to Date).
Second Generation: java.util.Calendar
Calendaris an abstract class that provides methods for converting between a specific instant and calendar fields likeYEAR,MONTH,DAY_OF_MONTH,HOUR, etc.- Created via
Calendar.getInstance(). - Note: Months are zero-based (0 for January). There is no built-in formatting; developers must combine fields manually.
import java.util.Calendar;
public class CalendarExample {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
System.out.println("Year: " + c.get(Calendar.YEAR));
System.out.println("Month: " + (c.get(Calendar.MONTH) + 1)); // +1 needed
System.out.println("Day: " + c.get(Calendar.DAY_OF_MONTH));
System.out.println("Hour: " + c.get(Calendar.HOUR_OF_DAY));
System.out.println("Minute: " + c.get(Calendar.MINUTE));
System.out.println("Second: " + c.get(Calendar.SECOND));
// Manual formatting
System.out.println(c.get(Calendar.YEAR) + "-" +
(c.get(Calendar.MONTH) + 1) + "-" +
c.get(Calendar.DAY_OF_MONTH) + " " +
c.get(Calendar.HOUR_OF_DAY) + ":" +
c.get(Calendar.MINUTE) + ":" +
c.get(Calendar.SECOND));
}
}
Third Geneartion: java.time.* (JDK 8)
Classes:
LocalDate: Date (year-month-day).LocalTime: Time (hour-minute-second-nanosecond).LocalDateTime: Date and time.DateTimeFormatter: For formatting and parsing.Instant: Represents an instantaneous point on the timeline (timestamp), similar toDate.
Advantages over previous generations:
- Immutable and thread-safe.
- No offset issues (e.g., month indexing from 1).
- Clear separation between date and time components.
- Support for operations like
plusDays,minusMinutes.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExample {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
System.out.println("Current: " + ldt);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = formatter.format(ldt);
System.out.println("Formatted: " + formatted);
System.out.println("Year: " + ldt.getYear());
System.out.println("Month: " + ldt.getMonth());
System.out.println("Month value: " + ldt.getMonthValue());
System.out.println("Day: " + ldt.getDayOfMonth());
System.out.println("Hour: " + ldt.getHour());
System.out.println("Minute: " + ldt.getMinute());
System.out.println("Second: " + ldt.getSecond());
// Plus and minus operations
LocalDateTime future = ldt.plusDays(890);
System.out.println("890 days later: " + formatter.format(future));
LocalDateTime past = ldt.minusMinutes(3456);
System.out.println("3456 minutes ago: " + formatter.format(past));
}
}
Instant (Timestamp)
import java.time.Instant;
import java.util.Date;
public class InstantExample {
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println("Instant now: " + now);
// Instant to Date
Date date = Date.from(now);
System.out.println("Date: " + date);
// Date to Instant
Instant instant = date.toInstant();
System.out.println("Converted back: " + instant);
}
}
More Third-Generation Methods
MonthDay: Useful for checking recurring events (e.g., birthdays).isLeapYear(): Check if a year is a leap year.plus/minus: Generic methods for adding/subtracting temporal amounts.
Third-generation date/time API is thread-safe, immutable, and provides comprehensive functionality. It is recommended for new projects.