上一篇文章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)); } }