Java8之默认方法和静态接口方法
前言
上一篇文章30分钟入门Java8之lambda表达式,我们学习了lambda表达式。现在继续Java8新语言特性的学习,今天,我们要学习的是默认方法和静态接口方法。
这一Java8的新语言特性,在Android N中也得到了支持。至于如何在Android开发中配置Java8的开发环境,请查看上一篇文章30分钟入门Java8之lambda表达式。
默认方法
默认方法让我们能给我们的软件库的接口增加新的方法,并且能保证对使用这个接口的老版本代码的兼容性。
下面通过一个简单的例子来深入理解下默认方法:
- 1.一天,PM说我们的产品需要获取时间和日期。于是我们就写了一个设置和获取日期时间的接口类
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说我们这个产品呐,不光国内用,各种其他时区的顾客也会使用。于是给你增加了新的需求:获取指定时区的日期和时间
以往我们都会这么做:
重写接口,增加方法
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));
}
}
Java8之默认方法和静态接口方法的更多相关文章
- 30分钟入门Java8之默认方法和静态接口方法
30分钟入门Java8之默认方法和静态接口方法 前言 上一篇文章30分钟入门Java8之lambda表达式,我们学习了lambda表达式.现在继续Java8新语言特性的学习,今天,我们要学习的是默认方 ...
- [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- CLR 虚方法调用和接口方法调用
不知接口方法和虚方法分发有什么区别?似乎在CIL中都是callvirt指令. 对,MSIL里都是callvirt,但JIT的时候得到了不同的处理:对虚方法的分发是编译成这样: mov ecx, es ...
- java8新特性(2)--接口的默认方法
1.默认方法的定义和作用 在Java8以前的版本中,由接口定义的方法是抽象的,不包括方法体.JDK8版本的发布改变了这一点,其中给接口添加了一个新的功能:默认方法.默认方法允许为接口方法定义默认实现. ...
- 改善JAVA代码01:考虑静态工厂方法代替构造器
前言 系列文章:[传送门] 每次开始新的一本书,我都会很开心.新书新心情. 正文 静态工厂方法代替构造器 说起这个,好多可以念叨的.做了一年多的项目,慢慢也有感触. 说起构造器 大家很明白,构造器 ...
- 创建对象_工厂方法(Factory Method)模式 与 静态工厂方法
工厂方法模式: 定义:为创建对象定义一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟至子类. 应用场景: 客户类不关心使用哪个具体类,只关心该接口所提供的功能: 创建过程比较 ...
- 初识面向对象-封装、property装饰器、staticmathod(静态的方法)、classmethod(类方法) (五)
封装 # class Room:# def __init__(self,name,length,width):# self.__name = name# self.__length = length# ...
- Effective Java 读书笔记(一):使用静态工厂方法代替构造器
这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...
- 比较 Java 静态工厂方法与构造函数
1 什么是静态工厂方法 Java 静态工厂方法是在方法前加上 public static,让这个方法变为公开.静态的方法.该方法返回该类的一个实例,就好像一个工厂生产出一个产品.所以称之为静态工厂方法 ...
随机推荐
- Subversion服务器搭建
如何快速建立Subversion服务器,并且在项目中使用起来,这是大家最关心的问题,与CVS相比,Subversion有更多的选择,也更加的容易,几个命令就可以建立一套服务器环境,可以使用起来,这里配 ...
- java jfinal + ajaxfileupload.js 上传
功能上传 需求:同时上传多张图片 前端:jquery.ajaxfileupload.js 后端:jfinal upload.htm <html> <body> <div ...
- POI导入
public void import(){ XSSFWorkbook wb = new XSSFWorkbook(new File("filePath")); XSSFSheet ...
- What are the main disadvantages of Java Server Faces 2.0?
http://stackoverflow.com/questions/3623911/what-are-the-main-disadvantages-of-java-server-faces-2-0/ ...
- KMP字符串模式匹配学习笔记
KMP算法实验 1.编程计算模式串(子串)的next值.2.利用KMP算法在主串中找到模式串的位置. 参考代码:---------int getNexlVal( char * s, int j)// ...
- SpringMVC+spring-security+sitemesh+hibernate+freemarker整合-转
http://www.oschina.net/code/snippet_170632_46774 代码分享 当前位置: 代码分享 » Java » Web编程 搜 索 SpringMVC+spr ...
- WCF入门教程四[WCF的配置文件]
一.概述 配置也是WCF编程中的主要组成部分.在 以往的.net应用程序中,我们会把DBConn和一些动态加载类及变量写在配置文件里.但WCF有所不同.他指定向客户端公开的服务,包括服务的地址. 服务 ...
- php 错误 Strict Standards: PHP Strict Standards: Declaration of .... should be compatible with that of 解决办法
错误原因:这是由于 php 5.3版本后.要求继承类必须在父类之后定义.否则就会出现Strict Standards: PHP Strict Standards: Declaration of ... ...
- OCR文字识别软件许可文件被误删了怎么办
使用任何一款软件,都会有误操作的情况发生,比如清理文件时一不小心删除了许可文件,对于ABBYY FineReader 12这样一款OCR文字识别软件,因失误错误删除了许可文件该怎么办呢?今天就来给大家 ...
- each和$(this)配合循环_siblings选取同级不同类型元素
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...