Java接口的几种常见用法

接口(interface)对于面向对象编程来说是一个非常重要的概念。它是一系列方法的声明,却没有具体实现。有些编程语言,比如swift,把接口解释成“协议(protocol)”,我觉得也是非常的恰当的,接口就是对方法制定的一套规范。

总结了以下几点接口的常见用法

1. 作为对类内执行流程的具体描述

这是接口的最根本的作用。有时候类内部流程的某一个环节,并不是由此类自己决定的。类并不知道在这一步时具体会执行什么内容。所以需要在此处设置一枚接口,提供对外界的扩展。

对于这个功能有一个非常好的范例。

一个秒表类:用于测量执行某一段代码执行所需的时间。

初步的代码类似于下面这样:

public class Stopwatch {private long deltaTime;public void clear() {deltaTime = 0L;}public long getDeltaTime() {return deltaTime;}public void start() {long startTime = System.currentTimeMillis();// do somethingdeltaTime = System.currentTimeMillis() - startTime;}
}

而使用Stopwatch的代码类似于这样:

public static void main(String[] args) {Stopwatch stopwatch = new Stopwatch();stopwatch.clear();	//时间清零stopwatch.start();	//开始运行System.out.printf("time: %dms\n",stopwatch.getDeltaTime());
}

那么我们知道对于秒表这个类本身,它并不能决定自己在do something那个位置将会测量什么内容的代码。

也就是说此处代码将会由Stopwatch的外部决定。所以此处可以商定一个协议,也就是接口。Stopwatch决定自己开放出一个接口叫NeedMonitoringProgram需要监控的程序,其中doProgram()方法就是执行需要被监控的代码。外部在使用Stopwatch时只需要去实现NeedMonitoringProgram接口也就定义好了需要监测的代码。

public interface NeedMonitoringProgram {void doProgram();
}

Stopwatch赋予NeedMonitoringProgram对象

public class Stopwatch {private long deltaTime;private NeedMonitoringProgram program;public void setProgram(NeedMonitoringProgram program) {this.program = program;}public void start() {long startTime = System.currentTimeMillis();program.doProgram();deltaTime = System.currentTimeMillis() - startTime;}public interface NeedMonitoringProgram {void doProgram();}//省略clear()和getDeltaTime()方法
}

模拟测量1到1000000叠加求和所需时间

 
Stopwatch stopwatch = new Stopwatch();
Stopwatch.NeedMonitoringProgram program = new Stopwatch.NeedMonitoringProgram() {@Overridepublic void doProgram() {int sum = 0;int number = 1_000_000;for (int i = 0; i <= number; i++) {sum += i;}System.out.printf("sum: %d\n", sum);}
};
stopwatch.setProgram(program);
stopwatch.clear();
stopwatch.start();
System.out.printf("time: %dms\n",stopwatch.getDeltaTime());

假如说待测代码是需要外部参数的,并且也需要返回给外部执行结果的。也可以把接口方法改进一下。

添加一个Param类来存储参数。

private Param params = new Param();public void addParam(String key, Object value) {params.put(key, value);
}public interface NeedMonitoringProgram<RETURN_OBJECT> {RETURN_OBJECT doProgram(Param params);
}public class Param extends HashMap<String, Object> {}

start方法也可以直接加入NeedMonitoringProgram对象,减少使用时的步骤。 并且NeedMonitoringProgram类的泛型指定了返回类型。

public <T> T start(NeedMonitoringProgram<T> program) {long startTime = System.currentTimeMillis();T returnObject = program.doProgram(params);deltaTime = System.currentTimeMillis() - startTime;return returnObject;
}

在执行start()之前使用addParam()给代码赋值。而start()也会返回代码执行的结果。

Stopwatch stopwatch = new Stopwatch();
stopwatch.clear();
stopwatch.addParam("number", 1_000_000);
int sum = stopwatch.start(new Stopwatch.NeedMonitoringProgram<Integer>() {@Overridepublic Integer doProgram(Stopwatch.Param params) {int sum = 0;int number = (Integer)params.get("number");for (int i = 0; i <= number; i++) {sum += i;}return sum;}
});
System.out.printf("sum: %d\n", sum);
System.out.printf("time: %dms\n",stopwatch.getDeltaTime());

运用JDK8的lambda表达式甚至可以缩写为

int sum = stopwatch.start(params -> {int s = 0;int number = (Integer)params.get("number");for (int i = 0; i <= number; i++) {s += i;}return s;
});

虽然java没有函数对象这一概念,但是使用lambda可以充分表达一种函数式编程的思想,在这里接口即等同于代表了一个函数对象。

以上是接口最最根本的功能,广泛运用在AWT、Swing、Android这类图形化程序中。像XXXListener这些处理控件事件的接口都是运用了此功能。

2. 多态

可以把具体子类对象都当作父类来看,屏蔽不同子类对象之间的差异。

public interface Animal {void sayHello();
}
public class Cat implements Animal{@Overridepublic void sayHello() {System.out.println("I'm a cat.");}
}
public class Dog implements Animal{@Overridepublic void sayHello() {System.out.println("I'm a dog.");}
}
public static void main(String[] args) {Animal[] animals = new Animal[]{new Cat(), new Dog()};for (Animal animal : animals) {animal.sayHello();}
}

在这里把Cat和Dog都一视同仁的放入了Animal的数组内,并且批量处理。多态的功能其实和抽象类(abstract class)相同。

3. 用于隐藏方法的具体实现过程

一个简单的Dao

public interface UserDao {User findUser(int id);void addUser(User user);void updateUser(User user);void deleteUser(int id);
}

这个DaoFactory工厂类代表某一框架内部生成Dao的逻辑(超简化)

public class DaoFactory {public <T> T getDaoInstance(Class<T> clazz) {if(clazz == UserDao.class) {return new UserDaoImpl();} else if(……) {}}
}

那么我们在使用该框架时,只需要从DaoFactory中通过Dao的类型获得该Dao的具体实现对象。

我们只关心该Dao接口有哪些我们可以用的方法,而不会去关心这个Dao内部是怎么实现增删改查的。拿着这个Dao对象我们就可以去完成数据库的操作。也就是说接口为我们屏蔽了方法的具体实现,屏蔽了具体的实现类中一些杂乱无章的,对于使用者来说无用的中间方法。

4. 暴露分布式服务

public interface XXXService {}

在大型网站项目中,底层的服务都是基于分布式部署的。比如说Dubbo框架,在分布式项目中,接口和实现是分离于两个子项目中的。分布式的优势在于,通过架设多台服务提供者(provider)维持了服务提供的稳定性。只要不是所有服务提供者挂机,服务消费者(consumer)依然可以得到稳定的服务。对于服务消费者来说它并不关心服务是由谁提供的,只关心有哪些服务可以用,所以接口既屏蔽了方法的具体实现,甚至还可以接来自不同服务提供者的服务。在这里,接口起到了一个协议的作用,消费者需要哪些服务,由接口描述,同时提供者根据接口实现了自己的处理服务逻辑。

5. 赋予类某种能力

我们常常会遇到一些诸如XXXable,以able结尾的类

比如说java.io.Serializable这是赋予了类可序列化的能力

我们自己也可以写给类赋予能力的接口以及实现。

做过微信支付的应该都知道,对接微信支付需要发送包含xml字符串的HTTP请求。

那么就可以对微信支付功能封装一个客户端(Client)

那么大致步骤如下:

public class WechatClient{/*** 统一下单*/public void unifiedOrder() {//1. 生成xml//2. 发送HTTP请求//3. 处理请求结果}
}

接下来给客户端类赋予可发送HTTP请求的能力,声明一个接口:

public interface HttpSendable {//发送GET请求HttpResponse getHttps(String url);//发送包含raw富文本的POST请求HttpResponse postHttps(String url, String raw);
}

HttpSendable顾名思义就是可发送HTTP请求的能力

那么给客户端加上这个能力

public class WechatClient implements HttpSendable

这个能力的实现可以使用抽象父类实现,不会造成次要代码污染主要类的逻辑

public abstract class HttpSender implements HttpSendable{@Overridepublic HttpResponse getHttps(String url) {return null;}@Overridepublic HttpResponse postHttps(String url, String raw) {return null;}
}

HttpSender就是HTTP的发送者,当然它也有发送HTTP的能力HttpSendable然后客户端继承了它

public class WechatClient extends HttpSender implements HttpSendable{/*** 统一下单*/public void unifiedOrder() {//1. 生成xmlString xml = "";//代码略//2. 发送HTTP请求HttpResponse response = super.postHttps("https://", xml);//3. 处理请求结果//代码略}
}

像这样写代码,是不是会增加代码的可理解性了呢?

6. 作为常量接口

一般老java程序员都喜欢这么用,包括JDK内部也有这么用的。把一些常量扔在接口里面。

//申请状态常量
public interface ApplyStatusContants {public static final String STATIC_UNTREATED = "STATIC_UNTREATED";//未处理public static final String STATIC_ACCEPT = "STATIC_ACCEPT"; //通过public static final String STATIC_REJECT = "STATIC_REJECT"; //拒绝
}

不过自从JDK1.5以后新增了enum枚举类型。我们就不需要常量接口了,可以如下方式:

public enum ApplyStatus {UNTREATED, ACCEPT, REJECT
}

简单粗暴。

接口的用法还是特别灵活多变的,也许还有没有列举的用法,欢迎大家补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android矢量图 内存大,Android内存控制小技巧-使用矢量图来节省你的内存并简化你的开发。...

先上一个 位图和矢量图的 说明。外链网址已屏蔽维基百科里面有更详细的说明 我就不贴地址了。简单来说就是位图 比 矢量图要大。但是位图可以适用于各种场景。但是矢量图就只能显示一些有规律的图形。复杂的做不了或者是很难做。对于android来说&#xff0c;我们一般app里面 会…

linux下利用nohup后台运行jar文件包程序

Linux 运行jar包命令如下&#xff1a; 方式一&#xff1a; java -jar XXX.jar 特点&#xff1a;当前ssh窗口被锁定&#xff0c;可按CTRL C打断程序运行&#xff0c;或直接关闭窗口&#xff0c;程序退出 那如何让窗口不锁定&#xff1f; 方式二 java -jar XXX.jar & &am…

idea 快捷键代码行标记并快捷跳到标记行

idea有一个组合快捷键 标记代码行&#xff08;左边的行数会出现一个1&#xff0c;代表着已经标记了&#xff09; ctrlshift1 迅速跳到标记行 ctrl1 这边给大家送上显示GIF

android十进制转十六进制算法,十进制转十六进制 代码

5621转换为16进制数的方法是“除16取余”方法&#xff0c;5621/16&#xff1d;商351余5&#xff0c;16进制最后一位为5351/16&#xff1d;商21余15&#xff0c;16进制右边第二位为F21/16&#xff1d;商1余5&#xff0c;16进制右边第三位为51/16&#xff1d;商0余1&#xff0c;1…

鸿蒙之火是什么意思,鸿蒙突然火了!鸿蒙是什么?

原标题&#xff1a;"鸿蒙"突然火了&#xff01;"鸿蒙"是什么&#xff1f;什么是鸿蒙&#xff1f;鸿蒙是什么&#xff1f;很多人都在发问&#xff0c;仿佛一夜之间就火了的鸿蒙有何独特之处&#xff1f;鸿蒙是真的来了。鸿蒙是文化&#xff0c;鸿蒙也是科技…

String类的indexOf方法的用法和举例

String类的indexof方法的作用和返回值&#xff1a; 今天在这里重点回顾一下&#xff0c;希望对大家能有所帮助&#xff1a; indexOf&#xff08;int&#xff0c;ch&#xff09; 先看第一个indexOf它返回值是int&#xff0c;在看它的参数&#xff08;int&#xff0c;ch&#x…

java中String对象作为参数传递问题

问题 java中将对象作为参数传递究竟是值传递还是引用传递&#xff1f; 1、基本类型作为参数传递时&#xff0c;是传递值的拷贝&#xff0c;无论你怎么改变这个拷贝&#xff0c;原值是不会改变的。 2、对象作为参数传递时&#xff0c;是把对象在内存中的地址拷贝了一份传给了参…

html语言怎么办到直接手写,4、手写HTML语言代码之《文字处理》

千里之堤始于足下!!学习网页制作的心得体会4.........手写HTML语言代码之《文字处理》一、和(居中对齐)下面网页我的第一个网页教师自制教学软件的背景随着教育体制的改革和信息时代的到来&#xff0c;可能越来越多的同学己经不再适应看着教师的板书、记着笔记的学习方式&#…

接口interface修饰符相关问题总结

1、抽象类中的抽象方法&#xff08;其前有abstract修饰&#xff09;不能用private、static、synchronized、native访问修饰符修饰。 原因如下&#xff1a; 抽象方法没有方法体&#xff0c;是用来被继承的&#xff0c;所以不能用private修饰&#xff1b;static修饰的方法可以通…

html纵向字幕无缝滚动,HTMl中marquee标签实现无缝滚动跑马灯效果示例

本篇文章小编给大家分享一下HTMl中marquee标签实现无缝滚动跑马灯效果示例&#xff0c;小编觉得挺不错的&#xff0c;现在分享给大家供大家参考&#xff0c;有需要的小伙伴们可以来看看。标签&#xff0c;它是成对出现的标签&#xff0c;首标签和尾标签之间的内容就是滚动内容。…

Java字符串池(String Pool)深度解析

在工作中&#xff0c;String类是我们使用频率非常高的一种对象类型。JVM为了提升性能和减少内存开销&#xff0c;避免字符串的重复创建&#xff0c;其维护了一块特殊的内存空间&#xff0c;这就是我们今天要讨论的核心&#xff0c;即字符串池&#xff08;String Pool&#xff0…

优酷html5视频网站,国内主要视频网站的嵌入方式

来一篇水文&#xff0c;整理一下国内各大视频网站的视频嵌入方式&#xff0c;或许有一点用处。爱奇艺、优酷、搜狐视频、腾讯视频、酷6、土豆、乐视。这些视频站绝大多数都采用 Flash 的方式播放&#xff0c;很多也提供了 iframe 的播放方式。根据最新标准应当使用 &#xff0c…

Java中取余(%)和取模(Math.floorMod)的区别

之前一直都认为取模和取余是一样的&#xff0c;甚至还怀疑设计语言的大神们不是脑子有问题么&#xff0c;为什么要整两个一样的东西&#xff0c;现在想想还是自己太 low了&#xff0c;竟然不能 get 到大神们的良苦用心。今天莫名其妙的用到了Java的取模方法&#xff0c;发现竟然…

用dl元素编辑html个人信息,html dl dt dd标签元素语法结构与使用

dl dt dd认识及dl dt dd使用方法一、dl dt dd认识 - TOPhtml 是一组合标签&#xff0c;使用了dt dd最外层就必须使用dl包裹&#xff0c;此组合标签我们也又叫表格标签&#xff0c;与table表格类似组合标签&#xff0c;故名我们也叫dl表格(扩展阅读&#xff1a;table tr td、…

千牛怎么注销卖家店铺_新店铺怎么拥有亚马逊购物车?亚马逊小卖家如何尽快获得黄金购物车?...

我做跨境电商也有六年的时间了&#xff0c;在电商这个行业也有自己的一些经验。经验也许没有其他大卖家丰富&#xff0c;但会将我知道的都进行分享。如果有不懂得亚马逊问题可以我(V&#xff1a;772024802)。我这里给大家安排一堂直播课&#xff0c;可以系统的帮你解决做亚马逊…

mysql中like是否使用索引

一.测试数据 CREATE TABLE test_orderdetail (id int(11) NOT NULL AUTO_INCREMENT,order_id int(11) DEFAULT NULL,product_name varchar(100) DEFAULT NULL,cnt int(11) DEFAULT NULL,create_date datetime DEFAULT NULL,PRIMARY KEY (id),KEY idx_orderid_productname (pro…

Ppt2010中HTML是什么,2010dw1html简介.ppt

2010dw1html简介课程名称&#xff1a;网页设计时间&#xff1a;周二 晚20:00到21:50地点&#xff1a;西配320教室教材&#xff1a;Dreamweaver网页设计案例教程weilei;第一节 网络及html简介;1.1 www的基本概念 ;1.2 网页访问流程( www的结构);1.3 浏览器;1.4网页设计基本概念 …

如何对一个对象进行深拷贝?

介绍 在Java语言里&#xff0c;当我们需要拷贝一个对象时&#xff0c;有两种类型的拷贝&#xff1a;浅拷贝与深拷贝。浅拷贝只是拷贝了源对象的地址&#xff0c;所以源对象的值发生变化时&#xff0c;拷贝对象的值也会发生变化。而深拷贝则是拷贝了源对象的所有值&#xff0c;…

电子科大16秋计算机应用基础在线作业一,电子科大16秋《计算机应用基础(本科)》在线作业3...

电子科技大学电子科大16秋《计算机应用基础(本科)》在线作业3一、单选题(共35 道试题&#xff0c;共70 分。)1. 在Windows,打开一个菜单后,其中某菜单项会出现下属级联菜单的标识是()。A. 菜单右侧有一组英文提示B. 菜单右侧有一个黑色三角形C. 菜单左侧有一个黑色圆点D. 菜单左…

wince手机投屏代码_除了 iOS,这些手机系统你肯定没用过

今年是2020年&#xff0c;智能手机市场经过大浪淘沙&#xff0c;留存下来的品牌可以说都是精品&#xff0c;国外的像苹果、三星、索尼、LG&#xff0c;国内有华为、小米、OV、魅族....都是有特色有竞争力的。华为在海外的巨幅广告牌但是大家有没有发现&#xff0c;如此多的手机…