上一篇文章30分鐘入門Java8之lambda表達式,咱們學習了lambda表達式。如今繼續Java8新語言特性的學習,今天,咱們要學習的是默認方法和靜態接口方法。html
這一Java8的新語言特性,在Android N中也獲得了支持。至於如何在Android開發中配置Java8的開發環境,請查看上一篇文章30分鐘入門Java8之lambda表達式。java
默認方法讓咱們能給咱們的軟件庫的接口增長新的方法,而且能保證對使用這個接口的老版本代碼的兼容性。ide
下面經過一個簡單的例子來深刻理解下默認方法:學習
TimeClient
。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(); }
以及這個接口的實現類SimpleTimeClient
:測試
public class SimpleTimeClient implements TimeClient { private LocalDateTime localDateTime; public SimpleTimeClient(){ localDateTime = LocalDateTime.now(); } @Override public void setTime(int hour, int minute, int second) { LocalTime localTime = LocalTime.of(hour, minute, second); LocalDate localDate = LocalDate.from(localDateTime); localDateTime = LocalDateTime.of(localDate,localTime); } @Override public void setDate(int day, int month, int year) { LocalDate localDate = LocalDate.of(day, month, year); LocalTime localTime = LocalTime.from(localDateTime); localDateTime = LocalDateTime.of(localDate, localTime); } @Override public void setDateAndTime(int day, int month, int year, int hour, int minute, int second) { LocalDate localDate = LocalDate.of(day, month, year); LocalTime localTime = LocalTime.of(hour, minute, second); localDateTime = LocalDateTime.of(localDate, localTime); } @Override public LocalDateTime getLocalDateTime() { return localDateTime; } @Override public String toString() { return localDateTime.toString(); } public static void main(String[] args) { TimeClient timeClient = new SimpleTimeClient(); System.out.println(timeClient.toString()); } }
2.但是PM說咱們這個產品吶,不光國內用,各類其餘時區的顧客也會使用。因而給你增長了新的需求:獲取指定時區的日期和時間code
以往咱們都會這麼作:htm
重寫接口,增長方法blog
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); }
這樣咱們的實現類也要相應的進行重寫。繼承
public class SimpleTimeClient implements TimeClient { private LocalDateTime localDateTime; ... ZonedDateTime getZonedDateTime(String zoneString){ return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString)); } 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(); } } }
這樣寫會致使咱們要去重寫每一個實現了TimeClient
接口的類。而這大大增長了咱們的實現需求的負擔。接口
正是爲了解決Java接口中只能定義抽象方法的問題。Java8新增長了默認方法的特性。下面讓咱們來使用默認方法實現需求。
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)); } }
默認方法關鍵字爲default
,以往咱們只能在接口中定義只有聲明沒有實現的方法。有了默認方法,咱們就能編寫完整的方法。
這樣咱們就不須要修改繼承接口的實現類,就給接口添加了新的方法實現。
public static void main(String[] args) { TimeClient timeClient = new SimpleTimeClient(); System.out.println(timeClient.toString()); System.out.println(timeClient.getZonedDateTime("test")); }
當咱們繼承含有默認方法的接口時,通常有如下三種狀況
//1.不去管默認方法 public interface AnotherTimeClient extends TimeClient{ }
經過下面的測試代碼,咱們知道AnotherTimeClient接口直接繼承了TimeClient接口的默認方法getZonedDateTime
Method[] declaredMethods = AnotherTimeClient.class.getMethods(); for(Method method:declaredMethods){ System.out.println(method.toString()); } //output: //public default java.time.ZonedDateTime xyz.johntsai.lambdademo.TimeClient.getZonedDateTime(java.lang.String)
//從新聲明默認方法,使之變爲抽象方法 public interface AbstractZoneTimeClient extends TimeClient{ @Override ZonedDateTime getZonedDateTime(String zoneString); }
測試能夠發現getZonedDateTime
方法由默認方法變爲了抽象方法:
Method[] methods = AbstractZoneTimeClient.class.getMethods(); for(Method method:methods){ System.out.println(method.toString()); } //output: //public abstract java.time.ZonedDateTime xyz.johntsai.lambdademo.AbstractZoneTimeClient.getZonedDateTime(java.lang.String)
//3.從新定義默認方法 public interface HandleInvalidZoneTimeClient extends TimeClient { default ZonedDateTime getZonedDateTime(String zoneString){ try { return ZonedDateTime.of(getLocalDateTime(), ZoneId.of(zoneString)); } catch (DateTimeException e) { System.err.println("Invalid zone ID: " + zoneString + "; using the default time zone instead."); return ZonedDateTime.of(getLocalDateTime(),ZoneId.systemDefault()); } } }
實現HandleInvalidZoneTimeClient
接口的類將擁有重寫過的getZonedDateTime
方法。
在Java8的接口中,咱們不光能寫默認方法,還能寫靜態方法。上面的例子中正好用到了靜態方法。
public interface TimeClient { // ... static public 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 public ZonedDateTime getZonedDateTime(String zoneString) { return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString)); } }