30分鐘入門Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí)
前言
上一篇文章30分鐘入門Java8之lambda表達(dá)式,我們學(xué)習(xí)了lambda表達(dá)式?,F(xiàn)在繼續(xù)Java8新語言特性的學(xué)習(xí),今天,我們要學(xué)習(xí)的是默認(rèn)方法和靜態(tài)接口方法。
這一Java8的新語言特性,在Android N中也得到了支持。至于如何在Android開發(fā)中配置Java8的開發(fā)環(huán)境,請(qǐng)查看上一篇文章30分鐘入門Java8之lambda表達(dá)式。
默認(rèn)方法
默認(rèn)方法讓我們能給我們的軟件庫(kù)的接口增加新的方法,并且能保證對(duì)使用這個(gè)接口的老版本代碼的兼容性。
下面通過一個(gè)簡(jiǎn)單的例子來深入理解下默認(rèn)方法:
1.一天,PM說我們的產(chǎn)品需要獲取時(shí)間和日期。于是我們就寫了一個(gè)設(shè)置和獲取日期時(shí)間的接口類 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();
}
以及這個(gè)接口的實(shí)現(xiàn)類 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說我們這個(gè)產(chǎn)品吶,不光國(guó)內(nèi)用,各種其他時(shí)區(qū)的顧客也會(huì)使用。于是給你增加了新的需求:獲取指定時(shí)區(qū)的日期和時(shí)間
以往我們都會(huì)這么做:
重寫接口,增加方法
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);
}
這樣我們的實(shí)現(xiàn)類也要相應(yīng)的進(jìn)行重寫。
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();
}
}
}
這樣寫會(huì)導(dǎo)致我們要去重寫每個(gè)實(shí)現(xiàn)了 TimeClient 接口的類。而這大大增加了我們的實(shí)現(xiàn)需求的負(fù)擔(dān)。
正是為了解決Java接口中只能定義抽象方法的問題。Java8新增加了默認(rèn)方法的特性。下面讓我們來使用默認(rèn)方法實(shí)現(xiàn)需求。
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();
}
}
//默認(rèn)方法
default ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
默認(rèn)方法關(guān)鍵字為 default ,以往我們只能在接口中定義只有聲明沒有實(shí)現(xiàn)的方法。有了默認(rèn)方法,我們就能編寫完整的方法。
這樣我們就不需要修改繼承接口的實(shí)現(xiàn)類,就給接口添加了新的方法實(shí)現(xiàn)。
public static void main(String[] args) {
TimeClient timeClient = new SimpleTimeClient();
System.out.println(timeClient.toString());
System.out.println(timeClient.getZonedDateTime( "test" ));
}
繼承含有默認(rèn)方法的接口
當(dāng)我們繼承含有默認(rèn)方法的接口時(shí),一般有以下三種情況
不去管默認(rèn)方法,繼承的接口直接繼承默認(rèn)方法
//1.不去管默認(rèn)方法
public interface AnotherTimeClient extends TimeClient{
}
通過下面的測(cè)試代碼,我們知道AnotherTimeClient接口直接繼承了TimeClient接口的默認(rèn)方法 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)
重新聲明默認(rèn)方法,這樣會(huì)使得這個(gè)方法變成抽象方法
//重新聲明默認(rèn)方法,使之變?yōu)槌橄蠓椒?
public interface AbstractZoneTimeClient extends TimeClient{
@Override
ZonedDateTime getZonedDateTime(String zoneString);
}
測(cè)試可以發(fā)現(xiàn) getZonedDateTime 方法由默認(rèn)方法變?yōu)榱顺橄蠓椒?
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)
重新定義默認(rèn)方法,這樣會(huì)使得方法被重寫
//3.重新定義默認(rèn)方法
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());
}
}
}
實(shí)現(xiàn) HandleInvalidZoneTimeClient 接口的類將擁有重寫過的 getZonedDateTime 方法。
靜態(tài)方法
在Java8的接口中,我們不光能寫默認(rèn)方法,還能寫靜態(tài)方法。上面的例子中正好用到了靜態(tài)方法。
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));
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決springboot 無法配置多個(gè)靜態(tài)路徑的問題
這篇文章主要介紹了解決springboot 無法配置多個(gè)靜態(tài)路徑的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
EditPlus運(yùn)行java時(shí)從鍵盤輸入數(shù)據(jù)的操作方法
這篇文章主要介紹了EditPlus運(yùn)行java時(shí)從鍵盤輸入數(shù)據(jù)的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Java中ArrayList在foreach里remove的問題詳析
這篇文章主要給大家介紹了關(guān)于Java中ArrayList在foreach里remove問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-09-09
spring-mvc/springboot使用MockMvc對(duì)controller進(jìn)行測(cè)試
這篇文章主要介紹了spring-mvc/springboot使用MockMvc對(duì)controller進(jìn)行測(cè)試,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
通過Java實(shí)現(xiàn)自己動(dòng)手寫ls命令
在前面的文章中,我們仔細(xì)的介紹了關(guān)于ls命令的使用和輸出結(jié)果,在本篇文章當(dāng)中我們用Java代碼自己實(shí)現(xiàn)ls命令,更加深入的了解ls命令2022-10-10
解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問題
這篇文章主要介紹了解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問題,具有很好的參考價(jià)值,希望對(duì)大家2021-08-08

