Chủ Nhật, 31 tháng 1, 2016

Java 8 Default Method


Java 8 bổ sung thêm “default method”. Default method là gì? Nó giải quyết những vấn đề gì? Bài post này sẽ trả lời những câu hỏi đó.
Problem
Giả sử tôi cần viết một module có chức năng thông báo định kỳ ngày giờ hiện tại. Tôi sẽ tạo interface TimeClient như sau:
Cùng với đó tôi có khoảng 3 class implement interface TimeClient này.
Bỗng một ngày đẹp trời tôi muốn thêm một chức năng vào interface này, ví dụ như khả năng chỉ định múi giờ qua ZonedDateTime object (giống với LocalDateTime nhưng có thêm tính năng lưu múi giờ).
Vậy là tôi phải sửa lại interface TimeClient như sau:
Và cùng lúc đó tôi phải sửa lại code của 3 class đã implement interface này. Điều này khá bất tiện. Với Java 8, tôi có thể khai báo một kiểu thực thi mặc định của method getZonedDateTime như sau:
Như vậy tôi không phải sửa code trong các class kia nữa, mà vẫn đảm bảo tính năng mới được thêm vào.
Chuyện vui: Khi project Lambda được xây dựng để đưa lambda expression vào Java 8, người ta cần thêm method forEach() vào các list/collection. Nhưng vấn đề là interface “List” hay “Collection” lại là 2 interface khác nhau, hơn nữa nếu thêm method forEach() vào interface thì tất cả các class implement 2 interface này cũng cần thêm method này. Còn nếu không thêm vào interface thì sẽ phá vỡ thiết kế hiện tại của Collection framework. Default method ra đời đã giải quyết được vấn đề, chỉ cần thêm một method default vào collection/list interface là tất cả các class có thể sử dụng được method này.
Nếu sử dụng default method một cách bừa bãi có thể gây ra diamond problem khi một class implement nhiều interface có default method cùng tên. Vậy Java giải quyết vấn đề này như thế nào? Bài sau sẽ rõ :D
import java.time.*;
public interface TimeClient {
void setTime(int hour, int minute, int second);
void setDate(int day, int month, int year);
void setDateAndTime(int day, int month, int year,
int hour, int minute, int second);
LocalDateTime getLocalDateTime();
}
import java.time.*;
public interface TimeClient {
void setTime(int hour, int minute, int second);
void setDate(int day, int month, int year);
void setDateAndTime(int day, int month, int year,
int hour, int minute, int second);
LocalDateTime getLocalDateTime();
ZonedDateTime getZonedDateTime(String zoneString);
}
import java.time.*;
public interface TimeClient {
void setTime(int hour, int minute, int second);
void setDate(int day, int month, int year);
void setDateAndTime(int day, int month, int year,
int hour, int minute, int second);
LocalDateTime getLocalDateTime();
static ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}

0 nhận xét: