Date-Time, I/O, NIO, and Serialization
Work correctly with time zones, files, paths, channels, buffers, streams, serialization concepts, and data boundaries.
The java.time API
Modern Java date-time APIs separate date, local date-time, instant, offset, and time zone.
Instant now = Instant.now();
LocalDate today = LocalDate.now();
ZonedDateTime india =
ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
Duration duration = Duration.between(
now, now.plusSeconds(30)
);
Use Instant for machine-oriented points in time, LocalDate for a date without a zone, and ZonedDateTime when location matters.
For financial systems, BigDecimal is generally preferred when decimal arithmetic must be exact.
A timestamp without its intended time-zone semantics can be ambiguous.
- Use
java.timefor new code. - Use
Instantfor absolute points in time. - Use explicit zones for human/business-local schedules.
Files, Paths, and I/O Streams
NIO.2 provides Path and Files for modern file operations.
Path path = Path.of("data", "users.txt");
Files.writeString(
path,
"Alice\nBob\n",
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING
);
String content = Files.readString(path);
Byte streams handle binary data; character readers/writers handle text. Buffered APIs reduce the cost of many small operations. For large files, stream line-by-line instead of loading the entire file.
PathandFilesare modern NIO.2 APIs.- Choose byte vs character APIs based on data semantics.
- Avoid loading huge files into memory when streaming is sufficient.
Channels, Buffers, and Non-Blocking I/O
NIO channels provide a lower-level I/O abstraction. Buffers hold data being transferred between application code and channels.
try (FileChannel channel =
FileChannel.open(Path.of("data.bin"), StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(4096);
int read = channel.read(buffer);
System.out.println("Read: " + read);
}
A ByteBuffer has position, limit, capacity, and remaining bytes. Calling flip() changes a buffer from writing mode to reading mode.
- Channels transfer data through buffers.
flip()prepares a written buffer for reading.- Use NIO directly when its control is valuable; otherwise prefer higher-level abstractions.
Serialization and Data Boundaries
Java's built-in object serialization has compatibility and security concerns. For network APIs, JSON, Protobuf, Avro, or other explicit formats are often better because the wire contract is visible and language interoperability is easier.
public record UserDto(String id, String name) {}
DTOs separate external representations from internal domain models. If a system consumes untrusted serialized data, treat deserialization as a security boundary and avoid arbitrary object construction.
Never treat untrusted serialized object data as harmless input. Prefer explicit, constrained data formats.
- Wire formats are API contracts.
- DTOs protect internal models from external coupling.
- Security must be considered at every deserialization boundary.