前言
上一篇文章30分鐘入門Java8之lambda表達式,我們學習了lambda表達式。現在繼續Java8新語言特性的學習,今天,我們要學習的是默認方法和靜態接口方法。
這一Java8的新語言特性,在Android N中也得到了支持。至于如何在Android開發中配置Java8的開發環境,請查看上一篇文章30分鐘入門Java8之lambda表達式。
默認方法
默認方法讓我們能給我們的軟件庫的接口增加新的方法,并且能保證對使用這個接口的老版本代碼的兼容性。
下面通過一個簡單的例子來深入理解下默認方法:
1.一天,PM說我們的產品需要獲取時間和日期。于是我們就寫了一個設置和獲取日期時間的接口類 TimeClient 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
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說我們這個產品吶,不光國內用,各種其他時區的顧客也會使用。于是給你增加了新的需求:獲取指定時區的日期和時間
以往我們都會這么做:
重寫接口,增加方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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); } |
這樣我們的實現類也要相應的進行重寫。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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新增加了默認方法的特性。下面讓我們來使用默認方法實現需求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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
,以往我們只能在接口中定義只有聲明沒有實現的方法。有了默認方法,我們就能編寫完整的方法。
這樣我們就不需要修改繼承接口的實現類,就給接口添加了新的方法實現。
1
2
3
4
5
6
7
8
9
|
public static void main(String[] args) { TimeClient timeClient = new SimpleTimeClient(); System.out.println(timeClient.toString()); System.out.println(timeClient.getZonedDateTime( "test" )); } |
繼承含有默認方法的接口
當我們繼承含有默認方法的接口時,一般有以下三種情況
不去管默認方法,繼承的接口直接繼承默認方法
1
2
3
4
|
//1.不去管默認方法 public interface AnotherTimeClient extends TimeClient{ } |
通過下面的測試代碼,我們知道AnotherTimeClient接口直接繼承了TimeClient接口的默認方法 getZonedDateTime
1
2
3
4
5
6
7
8
9
10
11
|
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) |
重新聲明默認方法,這樣會使得這個方法變成抽象方法
1
2
3
4
5
6
7
8
9
|
//重新聲明默認方法,使之變為抽象方法 public interface AbstractZoneTimeClient extends TimeClient{ @Override ZonedDateTime getZonedDateTime(String zoneString); } |
測試可以發現 getZonedDateTime 方法由默認方法變為了抽象方法:
1
2
3
4
5
6
7
8
9
10
11
|
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) |
重新定義默認方法,這樣會使得方法被重寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//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的接口中,我們不光能寫默認方法,還能寫靜態方法。上面的例子中正好用到了靜態方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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)); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/JohnTsai/p/5598036.html