Java 8的方法参考进一步限制了重载

方法重载一直是一个充满喜忧参半的话题。 我们已经在博客上介绍了它,并介绍了几次警告:

  • 您会后悔对Lambdas应用重载!
  • 保持干燥:方法重载
  • 为什么每个人都讨厌操作员超载
  • API设计师,请小心

重载有用的主要原因有两个:

  1. 允许使用默认参数
  2. 允许分离的参数类型替代

Bot原因仅仅是出于为API使用者提供便利的目的。 在JDK中很容易找到很好的例子:

默认参数

public class Integer {public static int parseInt(String s) {return parseInt(s,10);}public static int parseInt(String s, int radix) {}
}

在上面的示例中,第一个parseInt()方法只是使用最常用的基数调用第二个方法的一种简便方法。

析取参数类型替代

有时,使用不同类型的参数可以实现相似的行为,这意味着相似的事物,但在Java的类型系统中不兼容。 例如,当构造一个String

public class String {public static String valueOf(char c) {char data[] = {c};return new String(data, true);}public static String valueOf(boolean b) {return b ? "true" : "false";}// and many more...
}

如您所见,根据参数类型优化了相同方法的行为。 由于两个valueOf()方法的语义相同,因此在读写源代码时这不会影响该方法的“感觉”。

此技术的另一个用例是常用时,相似但不兼容的类型需要在彼此之间方便地转换。 作为API设计人员,您不想让这样繁琐的转换使您的API消费者感到无聊。 相反,您提供:

public class IOUtils {public static void copy(InputStream input, OutputStream output);public static void copy(InputStream input, Writer output);public static void copy(InputStream input, Writer output, String encoding);public static void copy(InputStream input, Writer output, Charset encoding);
}

这是一个很好的示例,它同时显示了默认参数(可选编码)以及参数类型替代项( OutputStreamWriterStringCharset编码表示形式)。

边注

我怀疑联合类型和默认参数船很早以前就已经为Java航行了-尽管联合类型可能被实现为语法糖,但是默认参数将是引入JVM的野兽,因为它将取决于JVM对Java的缺少支持。命名参数。

正如Ceylon语言所显示的那样,这两个功能覆盖了所有方法重载用例的99%,这就是为什么Ceylon可以在不重载的情况下完全完成-在JVM之上!

超载是危险且不必要的

上面的示例表明,重载实质上只是帮助人们与API交互的一种手段。 对于运行时,没有重载之类的东西。 调用仅以字节码“静态”链接到不同的,唯一的方法签名(给出或采用更新的操作码,例如invokedynamic)。 但是要点是,对于上述计算机,如果上述方法全部都称为copy() ,或者被明确地调用了m1()m2()m3()m4() ,则对计算机没有区别。

另一方面,重载在Java源代码中是真实的,并且编译器必须做大量工作才能找到最具体的方法,否则将应用JLS的复杂重载解析算法。 每个新的Java语言版本都会使情况变得更糟。 例如,在Java 8中,方法引用将给API使用者带来更多痛苦,并且需要API设计人员的额外照顾。 考虑一下Josh Bloch的以下示例:

//发现bug静态void pfc(List <Integer> x){x.stream()。map(Integer :: toString).forEach(s-> System.out.println(s.charAt(0))); }

— Joshua Bloch(@joshbloch) 2015年7月20日

您可以将上面的代码复制粘贴到Eclipse中,以验证编译错误(请注意,最新的编译器可能会报告类型推断副作用,而不是实际错误)。 Eclipse为以下简化报告了编译错误:

static void pfc(List<Integer> x) {Stream<?> s = x.stream().map(Integer::toString);
}

…是

Ambiguous method reference: both toString() and 
toString(int) from the type Integer are eligible

糟糕!

上面的表达是模棱两可的。 它可以表示以下两个表达式之一:

// Instance method:
x.stream().map(i -> i.toString());// Static method:
x.stream().map(i -> Integer.toString(i));

可以看出,使用lambda表达式而不是方法引用可以立即解决歧义。 解决此歧义(朝向实例方法)的另一种方法是改用toString()的超类型声明,该声明不再模糊不清:

// Instance method:
x.stream().map(Object::toString);

结论

API设计者的结论非常清楚:

自Java 8以来,方法重载已成为API设计人员更加危险的工具。

尽管上述内容并非真正“严峻”,但当API使用者的编译器拒绝看似正确的代码时,他们将花费大量时间来克服这种认知上的摩擦。 从该示例中获取的一个大人造假菜是:

切勿混合使用类似的实例和静态方法重载

实际上,这会放大您的静态方法重载何时重载java.lang.Object的名称, 正如我们在先前的博客文章中所解释的那样 。

遵循以上规则很简单。 因为只有两个有效的重载原因(默认参数和不兼容的参数替代),所以没有必要为同一类中的方法提供静态重载。 一个更好的设计(如JDK所公开)是具有“伴侣类”的,类似于Scala的伴侣对象。 例如:

// Instance logic
public interface Collection<E> {}
public class Object {}// Utilities
public class Collections {}
public final class Objects {}

通过更改方法的名称空间,可以在某种程度上很好地规避重载,并且不会出现以前的问题。

TL; DR:避免超载,除非增加的便利性真正增加了价值!

翻译自: https://www.javacodegeeks.com/2015/08/java-8s-method-references-put-further-restrictions-on-overloading.html

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

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

相关文章

多态性(C#)

在面向对象编程中继承性和多态性是重要机制&#xff0c;前面我为大家分享了我对“类的继承”的理解&#xff0c;哪么今天我就跟大家分享下我对“多态性(C#)”的理解。 首先我们先来看看多态的定义&#xff0c;同一操作作用于不同的对象&#xff0c;可以有不同的解释&#xff0c…

孙叫兽重磅推荐Chrome插件——CSDN浏览器助手

导读:解决你在浏览器上遇到的各种问题,无论你是学生小白、还是职场老鸟,都可以借助这个插件,打造个性化浏览器,提升工作学习效率。 此插件经过多轮迭代,体积小,内存占用少,便于开发者快速安装和使用。 官方地址:https://plugin.csdn.net/ 目录 安装方法:

mysql concat 引号_在MySQL concat里面使用多个单引号,三引号的问题

在动态拼接字符串时&#xff0c;我们常会用到字符拼接&#xff0c;我对拼接的引号不理解&#xff0c;如&#xff1a;1、 id 为什么是3个引号&#xff0c;为什么左边一个加号右边一个加号(能不能着重帮我解释下这个&#xff0c;详细点)SQL codesum(case Leave when id then D…

【APICloud系列|21】使用APICloud敏捷式开发总结,回顾开发一个完整APP过程。

导读:APICloud是柚子(北京)科技有限公司创建的低代码开发平台,总部位于北京, 通过生产力工具与混合开发技术,为企业与开发者构建高效的IT环境;在APICloud平台已有80万注册用户,平台每日生成安装包超6000个。业务团队延伸至上海、深圳、重庆、青岛等10余个城市。 APICloud是…

mysql 存储过程 记录是否存在_如何检查MySQL中是否存在存储过程?

让我们首先创建一个存储过程-mysql> DELIMITER //mysql> CREATE PROCEDURE ExtenddatesWithMonthdemo(IN date1 datetime, IN NumberOfMonth int )-> BEGIN-> SELECT DATE_ADD(date1,INTERVAL NumberOfMonth MONTH) AS ExtendDate;-> END;-> //mysql> DEL…

[ExtJS5学习笔记]第三十五条 sencha extjs 5 组件查询方法

一UI前部组件势必更加&#xff0c;我们通常习惯性使用ID获取部件操作的需要。但是&#xff0c;这种方法是extjs推荐么&#xff1f;你有吗extjs利用它来获取组件的推荐方法&#xff1f; 夹 文件夹extjs的查询组件的API查询实例主要的组件查询组件树查询通过组件的属性检索属性匹…

数据湖 多维数据集_按汇总分组/多维数据集

数据湖 多维数据集时不时地&#xff0c;您会遇到一个使您达到SQL限制的要求。 我们中的许多人可能会早早放弃并使用Java / [或您的语言]计算内容。 相反&#xff0c;使用SQL可能是如此简单快捷。 如果您使用的是高级数据库&#xff0c;例如DB2 &#xff0c; Oracle &#xff0c…

【APICloud系列|22】 videoPlayer模块(视频播放)的实现

导读:videoPlayer 封装了视频播放功能(不支持音频播放)。可快进、快退设置播放位置等操作,亦可设置屏幕亮度和系统声音大小。通过监听接口可获取模块上的各种手势操作事件。 模块详情:http://www.apicloud.com/mod_detail/35792 index.html <html><head>&l…

mysql数据库突然连不上了_mysql数据库突然连接不上去

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

FlexyPool如何同时支持连接代理和装饰器

代理人 FlexyPool监视连接池使用情况&#xff0c;因此需要拦截连接关闭方法调用。 为了简单起见&#xff0c;第一个版本为此目的依赖动态代理&#xff1a; private static class ConnectionInvocationHandler implements InvocationHandler {public static final String CLOS…

集合视图控制器(CollectionViewController) 、 标签控制器(TabBarController) 、 高级控件介绍...

1 创建集合视图&#xff0c;设置相关属性以满足要求 1.1 问题 集合视图控制器UIConllectionViewController是一个展示大量数据的控制器&#xff0c;系统默认管理着一个集合视图UICollectionView&#xff0c;功能几乎和UITableViewController差不多&#xff0c;能够以多行多列的…

【APICloud系列|23】 UIPullRefresh 模块(下拉刷新)的实现

导读:UIPullRefresh 模块对引擎新推出的下拉刷新接口进行了一层封装,App 可以通过此模块来实现带炫酷动画效果的下拉刷新功能。 使用了 window + frame 的布局,如果你只是使用在独立的 window 布局,那么就需要在 config.xml 中配置 <preference name="customRefres…

mysql迭代查询并分页_mysql 数据库 分页查询优化

举个栗子&#xff1a;表名&#xff1a;batch_big_num列名&#xff1a;id(主键)&#xff0c;name&#xff0c;age&#xff0c;product_name&#xff0c;product_num1&#xff0c;利用索引(1)加一个order by索引列 可以提升一定的效率select * from batch_big_num order by id …

【APICloud系列|24】 MNNavigationMenu模块(导航菜单)的实现

导读:MNNavigationMenu 是一个导航栏菜单,开发者可自定义其中的样式和按钮个数,超出屏幕部分可左右拖动查看。 模块详情:http://www.apicloud.com/mod_detail/12417 index.html <!doctype html> <html> <head><meta charset="utf-8">&…

mysql2教程_mySQL 教程 第2章 安装和介绍mySQL

设置mySQL字符集支持中文的字符集是utf8&#xff0c;该设置可以更改mySQL配置文件进行全局设置&#xff0c;也可以针对数据库设置&#xff0c;也可以针对表设置&#xff0c;也可以针对列设置。字符集更改后新插入的数据生效&#xff0c;对以前不生效。练习1&#xff1a;更改MyS…

java 更新订单状态_Java 8状态更新

java 更新订单状态即将到来的Java SE 8发行版的两大新语言功能是Lambda Expressions和Modularity。 这两天的状态更新都已经发布。 我会与您分享链接&#xff0c;因此您可能会在假期中通读它们 Oracle计划在2013年中期发布Java SE 8。 Lambda项目 Lambda项目以及JSR-335希望提…

有沃更精彩,沃课堂理想的移动学习平台

有沃更精彩。沃课堂&#xff0c;能够让你随时随地在你的手机上学习。在ipad上学习视频课程&#xff0c;能够在你闲暇时、等车时拿出你的pad,拿出你的手机来学习复习一段时间。让学习不在局限于互联网&#xff0c;局限于课堂上。 沃课堂。採用的是云server&#xff0c;全部的信息…

【APICloud系列|25】 easeChat模块(环信-即时通讯)的实现

导读&#xff1a;easeChat 模块封装了环信即时通讯云的开放SDK,封装的接口都是纯功能类接口&#xff0c; 主要分三大类&#xff1a; 1&#xff0c;注册、登录、退出、监听 2&#xff0c;创建群组、添加/删除好友、获取好友列表 3&#xff0c;消息、会话、聊天 功能详情参考模块…

mysql dump 10.13_mysqldump版本引起的问题

mysqldump5.1版本mysqldump --versionmysqldump Ver 10.13 Distrib 5.1.73, for redhat-linux-gnu (x86_64)mysqldump --help | grep gtid没有内容mysql5.6版本mysqldump --versionmysqldump Ver 10.13 Distrib 5.6.25, for Linux (x86_64)mysqldump --help | grep gtid--set…

基于JBoss Fuse 6.2的JBoss BPM微服务集成指南

今年年初&#xff0c;我们宣布了JBoss BPM Suite令人兴奋的示例项目&#xff0c;该项目围绕一个正在运行的在线Travel Agency项目展开。 最初是利用Web服务&#xff0c;后来我们在JBoss Fuse的帮助下迁移到微服务 。 随着JBoss Fuse 6.2的发布&#xff0c;我们希望重新访问该…