根据变量推断变量类型_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可能是对此功能的常见React。 对于大多数人来说,不能一直输入所有类型只是为了方便。 在阅读代码时,有些人可能希望看到明确记录下来的类型。 特别是,当您具有复杂的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/336404.shtml

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

相关文章

千元平板电脑排行榜_最值得买的平板电脑推荐-最佳平板电脑品牌排行榜【2020年10月】...

平板电脑相较笔记本电脑而言&#xff0c;以其便携与功能强大的特点成为大家日常生活和工作的必备搭档&#xff0c;无论在性能配置上还是在内置软件应用方面&#xff0c;不同的使用场景有不同的需求。今天给大家推荐最佳平板电脑品牌排行&#xff0c;希望对大家选购平板电脑有帮…

C++ One

class DeEncodec { public:static DeEncodec *Get(){static DeEncodec ff;return &ff;}protected:DeEncodec();};

mysql5建函数报1064错误,MySQL存储函数创建错误ERROR 1064和1327

我正在使用MySQL v5.1.36,我正在尝试使用此代码创建存储函数.DELIMITER //CREATE FUNCTION modx.getSTID (x VARCHAR(255)) RETURNS INT DETERMINISTICBEGINDECLARE y INT;SELECT id INTO yFROM modx.coverage_stateWHERE coverage_state.name x;RETURN y;END//当进入MysqL控制…

java 枚举 菜鸟_2个菜鸟Java常量和枚举陷阱

java 枚举 菜鸟在对Java和Groovy代码进行的各种代码审查中&#xff0c;我经常看到魔术数字和其他随机字符串散落在整个代码库中。 例如&#xff0c;下面的&#xff08;Groovy&#xff09;代码段中的4.2是一个神奇的数字&#xff1a; if (swashbuckle > 4.2) {... }4.2是什…

C++ 11 深度学习(二) 命名空间简介、基本输入输出精解

1.命名空间 作用:防止在大型工程中多个包含文件中的Fuction被重复定义使用造成不能编译的混乱。如下错误显示 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK2005 "void __cdecl showFirst(void)" (?showFirstYAXXZ) 已经在 first.obj 中定义 Project2 F:\…

python正则_python的正则表达式

上次小编写了正则表达式的用法&#xff0c;今天就小编就讲讲正则表达式再python中的应用&#xff0c;在python中想使用正则表达式就需要导入re模块。接下来小编将先介绍re模块中几个常见的函数findall:re.findall(‘正则表达式’&#xff0c;‘待匹配的内容’)例1&#xff1a;输…

【FFMPEG源码终极解析】 avformat_open_input (一)

avformat_open_input 打开媒体函数&#xff0c;先上全部源码。然后逐语句分析。 int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {//第一部分解析AVFormatContext *s *ps;int i, ret 0;AV…

spring async_Spring Async和Java的8 CompletableFuture

spring async众所周知&#xff0c;我不是Spring的最大粉丝&#xff0c;但是当时我在一个组织中工作&#xff0c;该组织使用Spring&#xff08;以不同的形式和版本&#xff09;维护了太多的项目。 我仍然对Spring持怀疑态度&#xff0c;当然有一些很好的主意&#xff0c;有一些很…

公里与英里的换算c语言函数_60迈=60码=60公里?这三者天壤之别,可别搞错了

说到行车速度&#xff0c;大家经常用的是这三个单位&#xff1a;码、迈、公里/时&#xff0c;很多人以为这三者是同一个意思&#xff0c;都是每小时多少公里。实际上这三者并不等同&#xff0c;下面小编科普一下这几个词的差异。码1码不等于1公里&#xff0c;而是等于0.9144米&…

php3.2.3分组查询,ThinkPHP3.2.3版本如何设置应用分组

鑫强已经解决了我的解决方法是创建两个入口文件实际上我的目的就是想要达到两个模块共用一个配置文件和公共函数文件我的解决方法是在项目根目录下建立两个入口文件一个是Index.php与Root.php两个入口文件其中是这样写的Index.php{<?php #前台入口文件 header(Conte…

FFmpeg options

libavformat options libavcodec options

通过图书编号查询python,基于Python的ISBN书号查询示例代码-六派数据

示例代码本代码示例是基于Python的六派数据接口进行数据请求API服务请求的代码示例&#xff0c;使用前你需要&#xff1a;以下是完整代码示例&#xff1a;#!/usr/bin/env python# -*- coding: utf-8 -*-# 测试环境: python2.7# 安装requests依赖 > pip install requests/ ea…

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

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

C++ 11 深度学习(一)auto、头文件防卫、引用、常量

1.数组初始化 int a[]{ 1,2,3,4,5 }; 2.C11 auto auto可以在声明变量的时候根据变量的初始值的类型自动为此变量先择合适的类型&#xff0c;声明时要赋予初值。 auto自动推导发生在编译期间 auto A 10;//A会被自动推导为int类型 3.头文件防卫式声明 作用:防止头文件重…

flux storm_Apache Storm:如何使用Flux配置KafkaBolt

flux storm微型框架中的助焊剂可以帮助我们定义和部署Storm拓扑。 Flux有各种包装器&#xff0c;可帮助您定义所需的流并初始化Bolts和Spouts&#xff08;使用带有或不带有参数的构造函数&#xff0c;并通过反射自动调用自定义配置方法&#xff09;。 您只需要使用Flux就是将…

android 在什么情况下会主动gc_Python 什么情况下会生成 pyc 文件?

作者&#xff1a;折木奉太郎(经授权转载)来源&#xff1a;https://www.zhihu.com/question/30296617/answer/112564303作为 Python 爱好者&#xff0c;需要了解 .py 脚本的基本运行机制及特性&#xff1a;在很多工作上&#xff0c;Python 的运行流程基本上取决于用户&#xff0…

oracle 查看内存参数配置,Oracle内存参数配置及版本问题

Oracle的内存配置与Oracle性能息息相关。从总体上讲&#xff0c;可以分为两大块&#xff1a;共享部分(主要是SGA)和进程独享部分(主要是PGA)。在 32 位操作系统下 的Oracle版本&#xff0c;不时有项目反馈关于内存的错误(如ORA-04030、04031错误)都是十分令人头疼的问题。查阅资…

【IP协议头分析】

Version 版本号 IHL IP头长度 Type of Service Total Length 总长度 Identification 拆包的唯一标识 Flags 1位保留 &#xff0c; 2位 允许拆包 3位 不允许拆包 Fragment offset 在原包偏移量 Time to Live 时间或路由跳数 Protocol IP中是什么协议类型 Header Check…