Java A的新本地变量类型推断

对于编程语言迷来说,新闻几乎比这更令人兴奋!

现在有一个状态为“候选”的本地变量类型推断的JEP 286 。 以及Brian Goetz的反馈请求,我很想邀请您参加: http : //mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000037.html

请这样做,调查仅在3月9日至3月16日开放!

这不是要实现的功能。 这可能实现。 因此,尚无特定的Java版本,这就是为什么我将Java版本命名为“ A”(对于Awesome)。

什么是局部变量类型推断,为什么好呢?

让我们看一下其他各种语言已经存在了一段时间的功能。 在此博客文章中,我想讨论总体思想,而不是讨论可能针对Java计划的特定实现,因为这还为时过早,而且我当然不了解如何将其适合Java。 。

在Java和其他某些语言中,类型总是明确和冗长地声明。 例如,您编写如下内容:

// Java 5 and 6
List<String> list = new ArrayList<String>();// Java 7
List<String> list = new ArrayList<>();

请注意,在Java 7中,如何通过有用的菱形运算符<>添加了一些语法糖。 它有助于以Java方式消除不必要的冗余,即通过应用“目标类型”,这意味着类型是由“目标”定义的。 可能的目标是:

  • 局部变量声明
  • 方法参数(从方法的外部和内部)
  • 班级成员

由于在许多情况下, 必须明确声明目标类型(方法参数,类成员),因此Java的方法很有意义。 但是,对于局部变量,实际上不需要声明目标类型。 由于类型定义绑定在一个非常局部的范围内,因此无法逃脱,因此编译器很可能会在没有源代码明确的情况下从“源类型”推断出它。 这意味着,我们将能够执行以下操作:

// Java A as suggested in the JEP// infers ArrayList<String>
var list = new ArrayList<String>();// infers Stream<String>
val stream = list.stream();

在上面的示例中, var表示可变(非最终)局部变量,而val表示不可变(最终)局部变量。 请注意,从来没有真正需要过列表类型,就像我们编写以下内容一样,今天已经推断出了类型:

stream = new ArrayList<String>().stream();

这与lambda表达式没有什么不同,在Java 8中我们已经有了这种类型推断:

List<String> list = new ArrayList<>();// infers String
list.forEach(s -> {System.out.println(s);
};

将lambda参数视为局部变量。 这种lambda表达式的另一种语法可能是:

List<String> list = new ArrayList<>();// infers String
list.forEach((val s) -> {System.out.println(s);
};

其他语言都有这个,但是好吗?

这些其他语言包括:C#,Scala和JavaScript(如果需要的话)。 YAGNI可能是对此功能的常见反应。 对于大多数人来说,不能一直输入所有类型只是为了方便。 某些人在阅读代码时可能更喜欢看到明确记录下来的类型。 特别是,当您具有复杂的Java 8 Stream处理管道时,很难跟踪沿途推断的所有类型。 在我们有关jOOλ的窗口函数支持的文章中可以看到一个示例:

BigDecimal currentBalance = new BigDecimal("19985.81");Seq.of(tuple(9997, "2014-03-18", new BigDecimal("99.17")),tuple(9981, "2014-03-16", new BigDecimal("71.44")),tuple(9979, "2014-03-16", new BigDecimal("-94.60")),tuple(9977, "2014-03-16", new BigDecimal("-6.96")),tuple(9971, "2014-03-15", new BigDecimal("-65.95")))
.window(Comparator.comparing((Tuple3<Integer, String, BigDecimal> t) -> t.v1, reverseOrder()).thenComparing(t -> t.v2), Long.MIN_VALUE, -1)
.map(w -> w.value().concat(currentBalance.subtract(w.sum(t -> t.v3).orElse(BigDecimal.ZERO))
));

上面实现了运行总计计算,得出:

+------+------------+--------+----------+
|   v0 | v1         |     v2 |       v3 |
+------+------------+--------+----------+
| 9997 | 2014-03-18 |  99.17 | 19985.81 |
| 9981 | 2014-03-16 |  71.44 | 19886.64 |
| 9979 | 2014-03-16 | -94.60 | 19815.20 |
| 9977 | 2014-03-16 |  -6.96 | 19909.80 |
| 9971 | 2014-03-15 | -65.95 | 19916.76 |
+------+------------+--------+----------+

尽管由于现有Java 8的有限类型推断功能而需要声明Tuple3类型( 另请参见有关广义目标类型推断的本文 ),但是您是否可以跟踪所有其他类型? 您可以轻松预测结果吗? 有些人喜欢短款,有些则声称:

另一方面,您是否想手动写下类似Tuple3<Integer, String, BigDecimal> ? 或者,在使用jOOQ时 ,您更喜欢以下哪个版本的相同代码?

// Explicit typing
// ----------------------------------------
for (Record3<String, Integer, Date> record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%"))
) {// Do things with recordString title = record.value1();
}// "Don't care" typing
// ----------------------------------------
for (Record record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%"))
) {// Do things with recordString title = record.getValue(0, String.class);
}// Implicit typing
// ----------------------------------------
for (val record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%"))
) {// Do things with recordString title = record.value1();
}

我敢肯定,很少有人真的愿意显式地写下整个泛型类型,但是如果您的编译器仍然可以记住这一点,那真是太棒了,不是吗? 这是一个可选功能。 您始终可以恢复为显式类型声明。

使用地点差异的边缘案例

没有这种类型推断,有些事情是不可能的,它们与使用站点的差异以及Java中实现的泛型的细节有关。 使用使用场所差异和通配符,可以构造无法分配给任何东西的“危险”类型,因为它们是不确定的。 有关详细信息,请阅读Ross Tate关于在Java的Type System中驯服通配符的论文 。

当从方法返回类型暴露时,使用站点差异也是一个痛苦,如在某些库中可以看到的:

  • 不在乎他们给用户带来的痛苦
  • 没有找到更好的解决方案,因为Java没有声明站点差异
  • 忽略了这个问题

一个例子:

interface Node {void add(List<? extends Node> children);List<? extends Node> children();
}

想象一下一个树数据结构库,其中树节点返回其子级列表。 从技术上讲正确的子类型为List<? extends Node> List<? extends Node>因为子级是Node子类型,并且使用Node子类型列表是完全可以的。

从API设计的角度来看,在add()方法中接受此类型非常有用。 例如,它允许人们添加List<LeafNode> 。 但是,从children()返回它是可怕的,因为现在唯一的选择是:

// Raw type. meh
List children = parent.children();// Wild card. meh
List<?> children = parent.children();// Full type declaration. Yuk
List<? extends Node> children = parent.children();

使用JEP 286,我们也许可以解决所有这些问题,并拥有第四个不错的选择:

// Awesome. The compiler knows it's 
// List<? extends Node>
val children = parent.children();

结论

局部变量类型推断是一个热门话题。 它是完全可选的,我们不需要它。 但这使很多事情变得容易得多,尤其是在使用大量仿制药时。 我们已经看到,在使用lambda表达式和复杂的Java 8 Stream转换时,类型推断是一项致命功能。 当然,要在一条较长的语句中跟踪所有类型会比较困难,但是同时,如果拼出了这些类型,则会使该语句非常难以阅读(并且通常也很难编写)。

类型推断有助于使开发人员提高工作效率,而又不放弃类型安全性。 实际上,这鼓励了类型安全,因为API设计人员现在不那么愿意向用户公开复杂的泛型类型,因为用户可以更轻松地使用这些类型( 请参见jOOQ示例 )。

实际上,此功能已经在各种情况下在Java中提供,只是在为局部变量赋值并为其命名时不存在。

无论您的意见是什么:请确保将其分享给社区并回答此调查: http : //mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000037.html

期待Java A,A代表Awesome。

翻译自: https://www.javacodegeeks.com/2016/03/java-new-local-variable-type-inference.html

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

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

相关文章

扩展kmp

拓展kmp是对KMP算法的扩展&#xff0c;它解决如下问题&#xff1a; 定义母串S&#xff0c;和字串T&#xff0c;设S的长度为n&#xff0c;T的长度为m&#xff0c;求T与S的每一个后缀的最长公共前缀 其中next数组表示T[i,m-1]和T的最长公共前缀 1 const int maxn100010; //字符…

linux中mysql导入数据库命令_linux下mysql数据库导入导出命令

首先linux 下查看mysql相关目录rootubuntu14:~# whereis mysqlmysql:/usr/bin/mysql—- mysql的运行路径/etc/mysql/usr/lib/mysql—– mysql的安装路径/usr/bin/X11/mysql/usr/share/mysql/usr/share/man/man1/mysql.1.gz此外还有一个&#xff1a;var/lib/mysql ——–mys…

转载:FilenameUtils的工具类

一、概述 这是一个Java操作文件的常用库&#xff0c;是Apache对java的IO包的封装&#xff0c;这里面有两个非常核心的类FilenameUtils跟FileUtils&#xff0c;其中FilenameUtils是对文件名操作的封装;FileUtils是文件封装&#xff0c;开发中对文件的操作&#xff0c;几乎都可以…

mysql 5.5.41 下载_MySQL 5.5.41/5.6.22 发布下载

MySQL 5.5.41 发布下载&#xff0c;此版本更新内容如下&#xff1a;编译改进移除了旧版本 Mac OS X 和 XCode 版本的CMake 工作区 (Bug #18510941)Previously, the MYSQL_MAINTAINER_MODE CMake option was turned on by default for debug builds and off for release builds…

envers_分代缓存和Envers

enversKonrad最近在我们公司的技术室中分享了有关如何完成缓存的有趣文章&#xff0c;这是一个大型的波兰社交网络nk.pl。 算法中的核心概念之一是分代缓存 &#xff08;请参阅此处或此处 &#xff09;。 基本思想是&#xff0c;对于缓存键&#xff0c;您使用一些特定于实体的字…

mysql ado.net 实体数据模型_Visual Studio2017中如何让Entity Framework工具【ADO.NET实体数据模型】支持MYSQL数据源...

熟悉Entity Framework应该对以下图片不陌生&#xff0c;他就是ADO.NET实体数据模型向导&#xff1a;可以将数据库的表自动生成模型类&#xff0c;或者创建Code First的模型文件。但是这个模型向导默认只显示微软自己的SQL Server数据源&#xff0c;如果想使用Mysql数据源&#…

ESP8266学习笔记6:ESP8266规范wifi连接操作

一、前言 我整理了从2015年至今关于ESP8266的学习笔记&#xff0c;梳理出来了开发环境、基础功能、进阶学习三大部分。方便自己和他人。可点此查看&#xff0c;欢迎交流。 之前在笔记4《ESP8266的SmartConfig》http://blog.csdn.net/iotisan/article/details/54849410中&#x…

使用Java 8进行分组,转换和归约

1.简介 在上一篇文章中 &#xff0c;我写了关于如何使用流和分组对对象集合进行分组的文章。 这很有用&#xff0c;但不涵盖特定的用例。 例如&#xff0c;有时我们不仅需要对事物进行分组&#xff0c;还需要将结果转换为更合适的对象。 在这篇文章中&#xff0c;我们将学习如…

rhel6.9 yum安装mysql_在RHEL6.9上安装MySQL5.7

通过YUM方式安装MySQL 5.7Step 1、下载MySQL源wget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpmyum localinstall mysql-community-release-el6-5.noarch.rpmStep 2、配额yum源并安装MySQLyum-config-manager --disable mysql55-communityyum-config-manager …

正则表达式的\b与\B总结

\b 单词边界&#xff0c;是指单词与符号之间的边界&#xff0c;是一个位置&#xff0c;不是空格或字符。(这里单词可以是中文字符&#xff0c;英文字符&#xff0c;数字&#xff1b;   符号可以是中文符号&#xff0c;英文符号&#xff0c;空格&#xff0c;制表符&#xff0c…

php mysql 取最小值_php – 根据另一个值更新最小值 – MySql

循环遍历数组并检查num是否低于前一个数字.$data数组的示例&#xff1a;$data array([0] > array(id > 9267399, code > 5D:148, num > 64),[1] > array(id > 9267398, code > 5D:186, num > 71));–$array_to_add array();foreach($data AS $val) {…

关于flex,好像有12个属性非常重要

关于Flex&#xff0c;有12个属性非常重要 这几天在学习Flex布局&#xff0c;发现Flex真的好厉害&#xff01; Flex是Flexible Box的缩写&#xff0c;意为“弹性布局”&#xff0c;用来为盒模型提供最大的灵活性。 Flex是它能够简单、完整、响应式的实现各种网页布局&#xff0c…

在Hibernate中启用实体和查询缓存

1.简介 在我执行过的与性能相关的任务中&#xff0c;这就是其中之一。 令人担心的是&#xff0c;如果每次为特定实体调用相同的查询&#xff0c;并且表数据在特定的时隙内不易更改&#xff0c;则我们可以使用Hibernate缓存查询结果。 这意味着&#xff0c;如果我们需要ID为1234…

php的内置函数strrpos_php strrpos 字符串查找函数内部源码实现

此函数strrpos从字符串的末尾开始查找所需要查找的字符。其他内部实现和strpos差不多是一样的。/* {{{ proto int strrpos(string haystack, string needle [, int offset]) Finds position of last occurrence of a string within another string */PHP_FUNCTION(strrpos){…

MyBatis缓存与Apache Ignite的陷阱

一周前&#xff0c;MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存&#xff08;L2缓存&#xff09;。 从技术上讲&#xff0c;MyBatis支持两个级别的缓存&#xff1a; 本地缓存&#xff0c;默认情况下始终启用 L2缓存&#xff0c;可选 随着Apache Ignite项目…

pptp mysql 认证_CentOS6.5搭建PPTP+Freeradius整合***管理系统

1、搭建PPTP服务php一、安装yum源mysql[rootNode ~]# cd /etc/yum.repos.d[rootNode ~]# wget http://mirrors.163.com/.help/CentOS6-Base-163.repo[rootNode ~]# yum -y install epel-relaese或web[rootNode ~]# rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/epel/6/x86_6…

OAuth2.0详解

来源博客&#xff1a;http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html OAuth是一个关于授权&#xff08;authorization&#xff09;的开放网络标准&#xff0c;在全世界得到广泛应用&#xff0c;目前的版本是2.0版。本文对OAuth 2.0的设计思路和运行流程&#xff0c;做…

python创建方法draw_Python做图像处理(五)---ImageDraw综合应用实例:自制验证码...

前面几讲讲解了pillow库中两个最重要的模块&#xff0c;Image模块与ImageDraw模块&#xff0c;本讲小编将这两个模块综合应用起来&#xff0c;来制作一个随机自动生成验证码的程序。1.生成验证码程序的算法设计原理验证码通常用于网络&#xff0c;是网站为了防止恶意注册和网络…

java web mvc_构建Java Web应用程序时遵循MVC的三个步骤

java web mvc第1步 做 始终通过servlet / action bean处理URL&#xff08;POST表单&#xff0c;单击链接等&#xff09;&#xff0c;而不是通过JSP处理 为什么 ActionBeans&#xff08;无论某些框架调用那些类&#xff09;&#xff0c;而servlet很少是控制器 用于处理用户输入。…

unknown error mysql_mysql执行sql文件报错Error: Unknown storage engine‘InnoDB’的解决方法...

发现问题最近在工作中遇到一个问题&#xff0c;在运行了一个innoDB类型的sql文件&#xff0c;报了Error: Unknown storage engine InnoDB错误&#xff0c;网上查了很多方法&#xff0c;但是都没办法真正解决我的问题&#xff0c;后来解决了&#xff0c;在这里总结一下过程&…