您会后悔对Lambdas应用重载!

编写好的API很难。 非常辛苦。 如果您想让用户喜欢您的API,则必须考虑很多事情。 您必须在以下两者之间找到适当的平衡:

  1. 有用性
  2. 易用性
  3. 向后兼容
  4. 前向兼容性

之前,在我们的文章: 如何设计良好的常规API中,我们已经就此主题进行过博客讨论。 今天,我们将研究如何…

Java 8更改规则

ryNBGfQ

是!

重载是一个很好的工具,可以在两个方面提供便利:

  • 通过提供参数类型替代
  • 通过提供参数默认值

来自JDK的上述示例包括:

public class Arrays {// Argument type alternativespublic static void sort(int[] a) { ... }public static void sort(long[] a) { ... }// Argument default valuespublic static IntStream stream(int[] array) { ... }public static IntStream stream(int[] array, int startInclusive, int endExclusive) { ... }
}

jOOQ API显然充满了这种便利。 由于jOOQ是SQL的DSL ,我们甚至可能会滥用一点:

public interface DSLContext {<T1> SelectSelectStep<Record1<T1>> select(SelectField<T1> field1);<T1, T2> SelectSelectStep<Record2<T1, T2>> select(SelectField<T1> field1, SelectField<T2> field2);<T1, T2, T3> SelectSelectStep<Record3<T1, T2, T3>> sselect(SelectField<T1> field1, SelectField<T2> field2, SelectField<T3> field3);<T1, T2, T3, T4> SelectSelectStep<Record4<T1, T2, T3, T4>> select(SelectField<T1> field1, SelectField<T2> field2, SelectField<T3> field3, SelectField<T4> field4);// and so on...
}

诸如Ceylon之类的语言通过声称以上内容是在Java中使用重载的唯一合理原因,将便利性这一概念进一步提高了。 因此,锡兰(Ceylon)的创建者已完全消除了其语言中的重载,将以上内容替换为联合类型和参数的实际默认值。 例如

// Union types
void sort(int[]|long[] a) { ... }// Default argument values
IntStream stream(int[] array,int startInclusive = 0,int endInclusive = array.length) { ... }

阅读“我希望我们在Java中拥有的十大锡兰语言功能” ,以获取有关锡兰的更多信息。

不幸的是,在Java中,我们不能使用联合类型或参数默认值。 因此,我们必须使用重载为API使用者提供便捷的方法。

但是,如果您的方法参数是一个函数接口 ,则在方法重载方面,Java 7和Java 8之间的情况发生了巨大变化。 JavaFX在此提供了一个示例。

JavaFX的“不友好”的ObservableList

JavaFX通过使它们“可观察”来增强JDK集合类型。 不要与Observable混淆, Observable是JDK 1.0和Swing之前的恐龙类型。

JavaFX自己的Observable本质上是这样的:

public interface Observable {void addListener(InvalidationListener listener);void removeListener(InvalidationListener listener);
}

幸运的是,这个InvalidationListener是一个功能接口:

@FunctionalInterface
public interface InvalidationListener {void invalidated(Observable observable);
}

这很棒,因为我们可以做以下事情:

Observable awesome = FXCollections.observableArrayList();
awesome.addListener(fantastic -> splendid.cheer());

(请注意,我是如何用更愉快的术语替换foo / bar / baz的。我们都应该这样做。Foo和bar是如此1970 )

不幸的是,当我们做我们可能要做的事情时,事情变得更加繁琐。 也就是说,与其声明一个ObservableObservable是一个更加有用的ObservableList

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener(fantastic -> splendid.cheer());

但是现在,我们在第二行收到编译错误:

awesome.addListener(fantastic -> splendid.cheer());
//      ^^^^^^^^^^^ 
// The method addListener(ListChangeListener<? super String>) 
// is ambiguous for the type ObservableList<String>

因为,本质上...

public interface ObservableList<E> 
extends List<E>, Observable {void addListener(ListChangeListener<? super E> listener);
}

和…

@FunctionalInterface
public interface ListChangeListener<E> {void onChanged(Change<? extends E> c);
}

再一次,在Java 8之前,这两种侦听器类型是完全可区分的,并且仍然是。 您可以通过传递命名类型来轻松调用它们。 如果我们编写以下代码,我们的原始代码仍然可以使用:

ObservableList<String> awesome = FXCollections.observableArrayList();
InvalidationListener hearYe = fantastic -> splendid.cheer();
awesome.addListener(hearYe);

要么…

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener((InvalidationListener) fantastic -> splendid.cheer());

甚至…

ObservableList<String> awesome = FXCollections.observableArrayList();
awesome.addListener((Observable fantastic) -> splendid.cheer());

所有这些措施将消除歧义。 但坦率地说,如果您必须显式键入lambda或参数类型,则lambda的性能只有后者的一半。 我们拥有现代化的IDE,它们可以执行自动补全并帮助推断类型,就像编译器本身一样。

想象一下,如果我们真的想调用另一个addListener()方法,它需要一个ListChangeListener。 我们必须写任何

ObservableList<String> awesome = FXCollections.observableArrayList();// Agh. Remember that we have to repeat "String" here
ListChangeListener<String> hearYe = fantastic -> splendid.cheer();
awesome.addListener(hearYe);

要么…

ObservableList<String> awesome = FXCollections.observableArrayList();// Agh. Remember that we have to repeat "String" here
awesome.addListener((ListChangeListener<String>) fantastic -> splendid.cheer());

甚至…

ObservableList<String> awesome = FXCollections.observableArrayList();// WTF... "extends" String?? But that's what this thing needs...
awesome.addListener((Change<? extends String> fantastic) -> splendid.cheer());

必须警惕。

API设计很难。 以前很难,现在变得越来越难。 在Java 8中,如果您的API方法的任何参数是功能接口,请三思而后行重载该API方法。 一旦您确定要继续进行重载,请再次思考,这是否真的是一个好主意。

不服气吗? 仔细看一下JDK。 例如java.util.stream.Stream类型。 您看到多少个具有相同数量的功能接口参数的重载方法,而这些接口又使用了相同数量的方法参数(就像我们前面的addListener()示例中一样)?

零。

在重载参数编号不同的地方有重载。 例如:

<R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);<R, A> R collect(Collector<? super T, A, R> collector);

调用collect()时,您永远不会有任何歧义。

但是,如果参数编号没有不同,并且参数本身的方法参数编号也没有变化,则方法名称也不同。 例如:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

现在,这在呼叫站点上非常令人讨厌,因为您必须事先考虑必须根据各种相关类型使用哪种方法。

但这确实是解决这一难题的唯一方法。 因此,请记住: 您会为Lambdas应用重载感到遗憾!

翻译自: https://www.javacodegeeks.com/2015/02/you-will-regret-applying-overloading-with-lambdas.html

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

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

相关文章

如何:优化Hive ZooKeeper Lock Manager实施

Hive一直使用ZooKeeper作为分布式锁定管理器来支持HiveServer2中的并发。 基于ZooKeeper的锁管理器在小型环境中运行良好。 但是&#xff0c;随着越来越多的用户从HiveServer迁移到HiveServer2并开始创建大量并发会话&#xff0c;可能会出现问题。 主要问题是Hiveserver2和ZooK…

《图解HTTP》第1章 了解Web及网络基础

《图解HTTP》第1章 了解Web及网络基础 1. 使用 HTTP 协议访问 Web1.1 网络基础 TCP/IP1.2 TCP/IP 协议族1.2.1 TCP/IP 的分层管理 1. 使用 HTTP 协议访问 Web Web 使用一种名为 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09; 的协议作为…

JBoss Forge NetBeans集成–入门

JBoss Forge是构建基于Maven的Java EE项目的最快方法。 因此&#xff0c;它已经具有了令人敬畏的功能&#xff0c;使您作为开发人员的生活更加轻松。 在大多数情况下&#xff0c;使用Forge的人们可能会对创建Web应用程序感兴趣。 有很多入门Forge基础的方法。 您可以查看quick…

SQL语法的重要知识点总结

好几年没写SQL语句了。现在到了新的team&#xff0c;需要用到数据库。作为QA的话时常需要使用客户端工具连接到数据库中找寻或修改数据。这么长时间没使用&#xff0c;一些SQL的使用技巧都忘得差不多了。晚上看了一些资料&#xff0c;花了1个多小时又捡起了曾经的知识。现在总结…

您需要了解的有关默认方法的所有信息

因此&#xff0c;默认方法是……昨天的新闻&#xff0c;对不对&#xff1f; 是的&#xff0c;但是使用一年后&#xff0c;积累了很多事实&#xff0c;我想将这些事实收集在一个地方&#xff0c;供刚开始使用它们的开发人员使用。 甚至有经验的人都可以找到他们不知道的一两个细…

php 在函数里打开链接,JavaScript中打开链接的几种方法介绍

如何使用JavaScript打开链接&#xff1f;本篇文章我们就来看看使用JavaScript打开链接的几种方法介绍。我们先来看一段代码使用Javascript实现打开链接&#xff0c;需要在location.href中替换要打开的链接的URL。location.href http://www.php.cn/blog.html;通过上述代码我们可…

三代基因组测序技术原理简介

考虑到cnblog不适合基因组领域这种类型的文章&#xff0c; 最终&#xff0c;我自己开通了公众号&#xff1a;碱基矿工&#xff0c;欢迎感兴趣的同学关注&#xff01; 也可以关注我的知乎&#xff1a;https://www.zhihu.com/people/yellowtree/activities 2018年1月修改&#x…

Java并发教程–锁定:显式锁定

1.简介 在许多情况下&#xff0c;使用隐式锁定就足够了。 有时&#xff0c;我们将需要更复杂的功能。 在这种情况下&#xff0c; java.util.concurrent.locks包为我们提供了锁定对象。 当涉及到内存同步时&#xff0c;这些锁的内部机制与隐式锁相同。 区别在于显式锁提供了其他…

lda php,主题模型︱几款新主题模型——SentenceLDA、CopulaLDA、TWE简析与实现

[导读]百度最近开源了一个新的关于主题模型的项目。文档主题推断工具、语义匹配计算工具以及基于工业级语料训练的三种主题模型&#xff1a;LatentDirichlet Allocation(LDA)、SentenceLDA 和Topical Word Embedding(TWE)。一、Familia简介帮Familia&#xff0c;打个小广告~ F…

最短路径问题matlab作图,[MATLAB基础] matlab最短路径的输出问题,用了递归,但程序出错了,请大虾指点...

matlab最短路径的输出问题,用了递归,但程序出错了,请大虾指点 程序如下function shortestpath(w,p,q)c->;l;f;tsize(w);mt(1,1);azeros(m,m);vw;for k1:mfor i1:mfor j1:mb[w(i,j),w(i,k)w(k,j)];w(i,j)min(b);if w(i,j)~v(i,j)a(i,j)k;%a(i,j)10*a(i,j)k;vw;endendendendw;…

快速浏览JAX-RS请求与方法匹配

在本文中&#xff0c;我们来看一下JAX-RS中与资源方法匹配的HTTP请求 。 它是JAX-RS的最基本功能之一。 通常&#xff0c;使用JAX-RS API的开发人员不会接触&#xff08;或真正不需要知道&#xff09; 匹配过程的细节&#xff0c;请放心&#xff0c;由于我们的RESTful&#xff…

$stat php,php stat函数怎么用

php stat函数用于返回关于文件的信息&#xff0c;其语法是fstat(file)&#xff0c;参数file必需&#xff0c;指规定要检查的文件。php stat函数怎么用&#xff1f;定义和用法stat() 函数返回关于文件的信息。语法fstat(file)参数file必需。规定要检查的文件。说明获取由 file 指…

Apache Cassandra和低延迟应用程序

介绍 多年来&#xff0c; Grid Dynamics拥有许多与NoSQL相关的项目&#xff0c;尤其是Apache Cassandra。 在这篇文章中&#xff0c;我们要讨论一个给我们带来挑战的项目&#xff0c;而我们在该项目中试图回答的问题今天也仍然适用。 数字营销和在线广告在2012年很受欢迎&…

Java十大简单性能优化

关于“ web scale ”这个流行词有很多炒作&#xff0c;人们花了很多时间来重新组织他们的应用程序体系结构&#xff0c;以使其系统“规模化”。 但是什么是扩展&#xff0c;我们如何确保可以扩展&#xff1f; 缩放的不同方面 上面提到的炒作主要是关于扩展负载 &#xff0c;即…

php在苹果手机上传不了图片大小,ThinkPHP后台上传图片无默认尺寸解决方法

原标题&#xff1a;ThinkPHP后台上传图片无默认尺寸解决方法随着网站移动端的日益普及&#xff0c;对后台数据的兼容性要求也越来越高。后台数据涵盖范围不断扩大的同时&#xff0c;使得程序处理能力也必须逐步提高。使用ThinkPHP进行长沙网站开发时&#xff0c;后台kindeditor…

宝塔php gd库,宝塔面板安装 EasyImag – 一款最简单图床的安装体验

近日闲逛&#xff0c;发现了一款图床&#xff0c;一款开箱即食的简单图床程序。因为没有数据库所以安装起来也是异常简单&#xff0c;我们看看功能&#xff1a;支持设置图片质量支持仅登录后上传支持QQ截图&#xff0c;剪切板上传支持在线管理(增删改查)支持上传图片转换为指定…

批准Oracle IDM中的特定Web服务

关于Web服务端点的快速发布&#xff0c;OIM和SOA在与批准有关的场景中使用了Web服务端点- 基本内容&#xff0c;但对于初学者可能有用 。 Oracle IDM与SOA套件集成并利用其提供与批准相关的功能&#xff08;说实话&#xff0c;SOA相当丰富&#xff0c;并且也被用作Web服务连接…

Oracle15001,Oracle11gR2RAC环境DBCA创建数据库报错ORA-15055ORA-15001

在Oracle 11gR2 GridInfrastructure和Database软件安装完成之后&#xff0c;执行DBCA创建数据库到30%的时候报如下错误&#xff0c;点击OK后提示忽略并问题现象:在Oracle 11gR2 GridInfrastructure和Database软件安装完成之后&#xff0c;执行DBCA创建数据库到30%的时候报如下错…

针对新手的Java EE7和Maven项目–第8部分

第1部分 &#xff0c; 第2部分 &#xff0c; 第3部分 &#xff0c; 第4部分 &#xff0c; 第5部分 &#xff0c; 第6部分 &#xff0c; 第7部分 第8部分 自上一篇文章以来&#xff0c;这一系列教程已经有很长时间了。 是时候恢复并在我们的简单项目中添加新功能了。 正…

玩Weld-Probe –一站式查看CDI的所有方面

焊接3.0.0.Alpha4被释放 &#xff0c;而我一直坐在在DevConf.CZ一间会议室。 Jozef Hartinger&#xff08; jozefhartinger &#xff09;或多或少地在几分钟前告诉我有关此最新版本的新功能的信息。 有一个特别的功能真正引起了我的注意&#xff0c;它是新的焊接探针机制。 什…