经过几天的Scala回归Java的10个最烦人的事情

因此,我正在尝试使用Scala,因为我想编写一个解析器,而Scala Parsers API似乎非常合适。 毕竟,我可以在Scala中实现解析器并将其包装在Java接口后面,因此除了附加的运行时依赖关系之外,不应该存在任何互操作性问题。

在几天后真正真正地习惯了Scala语法的强大功能之后,以下是我回到编写Java时最想错过的十件事:

1.多行字符串

这是我个人的最爱,也是一种非常棒的功能,应该使用任何语言。 甚至PHP都有:多行字符串。 就像写作一样简单:

println ("""Dear reader,If we had this feature in Java,
wouldn't that be great?Yours Sincerely,
Lukas""")

这在哪里有用? 使用SQL,当然! 这是使用jOOQ和Scala运行纯SQL语句的方法:

println(DSL.using(configuration).fetch("""SELECT a.first_name, a.last_name, b.titleFROM author aJOIN book b ON a.id = b.author_idORDER BY a.id, b.id""")
)

这不仅适用于静态字符串。 使用字符串插值,您可以轻松地将变量注入到这样的字符串中:

val predicate =if (someCondition)"AND a.id = 1"else""println(DSL.using(configuration)// Observe this little "s".fetch(s"""SELECT a.first_name, a.last_name, b.titleFROM author aJOIN book b ON a.id = b.author_id-- This predicate is the referencing the-- above Scala local variable. Neat!WHERE 1 = 1 $predicateORDER BY a.id, b.id""")
)

太棒了,不是吗? 对于SQL,Scala具有很大的潜力。

jooq在scala-smalll中编写SQL的最佳方法

2.分号

我真心没有错过他们一点。 我构造代码的方式(可能也是大多数人构造代码的方式),Scala似乎根本不需要分号。 在JavaScript中,我不会说同样的话。 JavaScript的解释性和非类型安全性质似乎表明,放弃可选的语法元素可以保证您一臂之力。 但是Scala不支持。

val a = thisIs.soMuchBetter()
val b = no.semiColons()
val c = at.theEndOfALine()

可能是由于Scala的类型安全性导致的,这将使编译器在那些罕见的模棱两可的情况下抱怨,但这只是有根据的猜测。

3.括号

这是一个雷区,在许多情况下,省略括号似乎很危险。 实际上,在调用方法时,您也可以忽略点:

myObject method myArgument

由于这种方法会产生大量歧义,尤其是在链接更多的方法调用时,我认为最好避免这种技术。 但是在某些情况下,“忘记”父母很方便。 例如

val s = myObject.toString

4.类型推断

在Java中,这真的很烦人,与此同时,似乎还有许多其他语言也做到了这一点。 Java仅具有有限的类型推断功能,而且事情并不尽如人意 。

在Scala中,我可以简单地写:

val s = myObject.toString

……而不关心s是String类型的事实。 有时,但仅在某些情况下,我希望明确指定引用的类型。 在那种情况下,我仍然可以做到:

val s : String = myObject.toString

5.案例分类

我想我想写另一个POJO,它具有40个属性,构造函数,getter,setter,equals,hashCode和toString

-没人说。 曾经

Scala具有案例类。 用单线编写的简单不可变的pojos。 以Person案例类为例:

case class Person(firstName: String, lastName: String)

我同意,必须确实写下一次属性。 但是其他一切应该是自动的。

以及如何创建此类案例类的实例? 轻松,你甚至都不需要new运营商(事实上,它完全逃脱了我的想象,为什么new真正需要摆在首位):

Person("George", "Orwell")

而已。 您还想写些什么以符合企业标准?

边注

好的,现在有些人会争辩说要使用lombok项目 。 基于注释的代码生成是胡说八道,应最好避免。 实际上,Java生态系统中的许多注释简单地证明了Java语言的(而且将永远是)其演化能力非常有限这一事实。 以@Override为例。 这应该是关键字,而不是注释。 您可能会认为这是表面上的区别,但是我说Scala已经证明注释几乎总是错误的工具。 还是您最近看过带有大量注释的 Scala代码?

6.到处都有方法(功能!)

我认为,这实际上是任何语言中最有用的功能之一。 为什么我们总是必须将方法链接到特定的类? 为什么我们不能简单地拥有任何作用域级别的方法? 因为我们可以,所以使用Scala:

// "Top-level", i.e. associated with the package
def m1(i : Int) = i + 1object Test {// "Static" method in the Test instancedef m2(i : Int) = i + 2def main(args: Array[String]): Unit = {// Local method in the main methoddef m3(i : Int) = i + 3println(m1(1))println(m2(1))println(m3(1))}
}

对? 为什么我不能在另一个方法中定义本地方法? 我可以使用Java中的类来做到这一点:

public void method() {class LocalClass {}System.out.println(new LocalClass());
}

局部类是方法局部的内部类。 这几乎没有用,但是真正有用的是局部方法。

JavaScript或REPL也支持这些功能。 这对于在应用程序范围之外测试小型算法或概念非常有用。

在Java中,我们通常倾向于这样做:

public class SomeRandomClass {// [...]public static void main(String[] args) {System.out.println(SomeOtherClass.testMethod());}// [...]
}

在Scala中,我将在REPL中编写以下代码:

println(SomeOtherClass.testMethod)

还请注意始终可用的println方法。 纯金方面的高效调试。

8.数组不是(很多)特例

在Java中,除了基本类型以外,还有一些我们称为数组的怪异事物。 数组起源于一个完全独立的宇宙,在这里我们必须记住起源于柯克上尉(大约)时代的古怪规则:

数组

是的,规则如下:

// Compiles but fails at runtime
Object[] arrrrr = new String[1];
arrrrr[0] = new Object();// This works
Object[] arrrr2 = new Integer[1];
arrrr2[0] = 1; // Autoboxing// This doesn't work
Object[] arrrr3 = new int[];// This works
Object[] arr4[] = new Object[1][];// So does this (initialisation):
Object[][] arr5 = { { } };// Or this (puzzle: Why does it work?):
Object[][] arr6 = { { new int[1] } };// But this doesn't work (assignment)
arr5 = { { } };

是的,清单可以继续。 从句法上讲,使用Scala,数组不再是一种特殊情况:

val a = new Array[String](3);
a(0) = "A"
a(1) = "B"
a(2) = "C"
a.map(v => v + ":")// output Array(A:, B:, C:)

如您所见,数组的行为与其他集合非常相似,包括可以在其上使用的所有有用方法。

9.符号方法名称

现在,这个话题更具争议性,因为它使我们想起了运算符重载的危险 。 但是,每隔一段时间,我们希望有类似的东西。 可以让我们写的东西:

val x = BigDecimal(3);
val y = BigDecimal(4);
val z = x * y

非常直观地,z的值应为BigDecimal(12) 。 那不能太难了,可以吗? 我不在乎*的实现是否真的是一个称为multiply()的方法。 写下该方法时,我想使用看起来很普通的运算符进行乘法。

顺便说一句,我也想用SQL做到这一点。 这是一个例子:

select ( AUTHOR.FIRST_NAME || " " || AUTHOR.LAST_NAME,AUTHOR.AGE - 10
)
from AUTHOR
where AUTHOR.ID > 10
fetch

那没有道理吗? 我们知道|| 表示concat(在某些数据库中)。 我们知道- (减号)和> (大于)的含义。 为什么不写呢?

上面是在Scala中的jOOQ的编译示例。

jooq最好的方式在scala中写sql小

注意:警告

允许操作符重载或符号方法名之类的东西总是存在缺点。 它可能(并将被)滥用。 图书馆与Scala语言本身一样多 。

10.元组

作为一个SQL人员,这再次是我在其他语言中最想念的功能之一。 在SQL中,所有内容都是TABLE或ROW。 实际上,很少有人知道这一点 ,并且很少有数据库实际上支持这种思维方式。

Scala没有ROW类型(实际上是记录),但是至少有匿名元组类型。 将行视为具有命名属性的元组,而案例类将命名为行:

  • 元组:具有类型化和索引元素的匿名类型
  • 行:具有类型化,命名和索引元素的匿名类型
  • 案例类:带有类型化元素和命名元素的命名类型

在Scala中,我可以这样写:

// A tuple with two values
val t1 = (1, "A")// A nested tuple
val t2 = (1, "A", (2, "B"))

在Java中,可以完成类似的操作,但是您必须自己编写该库,并且不提供语言支持:

class Tuple2<T1, T2> {// Lots of bloat, see missing case classes
}class Tuple3<T1, T2, T3> {// Bloat bloat bloat
}

然后:

// Yikes, no type inference...
Tuple2<Integer, String> t1 = new Tuple2<>(1, "A");// OK, this will certainly not look nice
Tuple3<Integer, String, Tuple2<Integer, String>> t2 =new Tuple3<>(1, "A", new Tuple2<>(2, "B"));

jOOQ充分利用了上述技术,将SQL的行值表达式带到Java,而且令人惊讶的是,在大多数情况下,您可以在不丢失类型推断的情况下做到这一点,因为jOOQ是一种流利的API,您从未真正将值分配给局部变量。例:

DSL.using(configuration).select(T1.SOME_VALUE).from(T1).where(// This ROW constructor is completely type saferow(T1.COL1, T1.COL2).in(select(T2.A, T2.B).from(T2))).fetch();

结论

当然,这是一篇有关scala的文章,与Java稍有抵触。 不要误会我的意思。 我绝不希望完全迁移到Scala。 我认为Scala语言远远超出了任何有用软件中的合理范围。 有许多看起来不错的小功能和头,但不可避免地会炸掉您的脸,例如:

  • implicit转换。 这不仅很难管理,而且还严重降低了编译速度。 此外,使用implicit合理地实现语义版本控制可能完全是不可能的,因为不可能通过偶然的向后不兼容预见所有可能的客户端代码损坏。
  • 本地导入乍一看似乎很棒,但是当人们开始部分导入或重命名本地范围的类型时,它们的功能很快使代码难以理解。
  • 符号方法名称最常被滥用。 以解析器API为例,它具有诸如^^^^^^?等方法名称^?~!

尽管如此,我认为本文中列出的Scala与Java相比的优点也可以全部用Java实现:

  • 几乎没有破坏向后兼容的风险
  • 用(可能)不太大的努力,在JLS方面
  • 对开发人员的生产力产生巨大影响
  • 对Java的竞争力产生巨大影响

无论如何,Java 9将是另一个有前途的版本,其热门话题包括值类型, 声明站点差异 , 特殊化(非常有趣!)或ClassDynamic。

有了这些巨大的变化,我们希望上面的一些小改进还有一定的余地,这将为日常工作增加更多的直接价值。

翻译自: https://www.javacodegeeks.com/2014/08/the-10-most-annoying-things-coming-back-to-java-after-some-days-of-scala.html

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

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

相关文章

LeetCode 198. 打家劫舍(House Robber) 5

198. 打家劫舍198. House Robber 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自…

SpringBoot 参数符号转义,用这个包下面的类

SpringBoot 参数符号转义&#xff0c;用这个包下面的类 org.apache.commons.text.StringEscapeUtils String team StringEscapeUtils.unescapeHtml4(biUserOrganization.getTeam()); 2017/12/01 | Java | admin| 暂无评论 | 8717 views如题所示&#xff0c;之前一直使用c…

irrlicht v1.6 例程18 Splitscreen

/** Example 018 Splitscreen, U( a# q, ( S f1 ]( p作者&#xff1a;Max Winkel." 9 ?( W; K V1 x8 \译&#xff1a;小时候可靓了&#xff08;履霜坚冰&#xff09;2 m! C! N# J2 i6 a2 Z! Q0 U2 D4 U: U% J1 E5 N! a0 L4 q& x这个例程中我们将学习怎么使用irrlicht…

检查Red Hat JBoss BRMS部署架构的规则和事件(第二部分)

&#xff08;文章来宾与北美红帽公司高级中间件顾问约翰赫洛克 &#xff08; John Hurlocker&#xff09;合着&#xff09; 在本周的技巧中&#xff0c;我们将放慢速度&#xff0c;并仔细研究可能的Red Hat JBoss BRMS部署体系结构。 当我们谈论部署架构时&#xff0c;我们指…

博客园皮肤-我的博客园皮肤设置教程

一、前言 好的博客皮肤能吸引更多的访问量&#xff0c;也可以使博主更有动力更新博客。今天看到一个博主的博客非常漂亮&#xff0c;突发奇想也打扮了一下自己的博客&#xff0c;虽然差距还有不小&#xff0c;也记录一下操作方法供大家参考。 二、操作 1.左上角“fork me on gi…

设计撑百万并发的数据库架构

设计撑百万并发的数据库架构 https://www.toutiao.com/a6742034135486824973/ 前言 作为一个全球人数最多的国家&#xff0c;一个再怎么凄惨的行业&#xff0c;都能找出很多的人为之付出。而在这个互联网的时代&#xff0c;IT公司绝对比牛毛还多很多。但是大多数都是创业公司&a…

Spring MVC集成测试:断言给定的模型属性有全局错误

为了使用Bean验证报告Spring MVC中的全局错误&#xff0c;我们可以创建一个自定义的类级别约束注释。 全局错误与已验证Bean中的任何特定字段都不相关。 在本文中&#xff0c;我将展示如何使用Spring Test编写测试&#xff0c;以验证给定的model属性是否存在全局验证错误。 自…

Intent 的用法

1、用Context指定 Intent inew Intent(context,Receivered.class); context.startActivity(i);2、通过配置指定 <activity android:name"com.neusoft.android.Demo.photo.TestActivity"> <intent-filter> <action android:n…

Tips_一级菜单栏实现

1.纵向 1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>menu01</title>6 <style type"text/css">7 *{8 margin: 0;9 pad…

数学基础 - 向量

1. 向量(Vector) 向量指具有大小和方向的量。 2 基(Basic,基底) 2.1 线性无关 在一个向量空间\(V_n\)中&#xff0c;假设&#xff1a; \(a_1e_1 ⋯ a_ne_n 0\)  (式1) 只在 \(a_1 ⋯ a_n 0\) 时成立&#xff0c;那么向量 \(\{e_1, e_2, ..., e_n\}\) 是线性无关的。 如…

2-使用git管理一个单片机程序

https://www.cnblogs.com/yangfengwu/p/10842205.html 我用电脑压缩一个文件,然后通过git上传,然后在新买的linux系统通过wget 网络下载这个压缩文件,然后死活解压不可以...无论是哪种格式的文件 一开始我怀疑是压缩软件压缩的问题,就换了一个压缩软件进行压缩,但是没有解决问题…

Java线程面试的前50个问题,面向初学者和经验丰富的程序员

您可以参加任何Java面试&#xff0c;无论是大四还是中级&#xff0c;经验或新来的人&#xff0c;一定会看到线​​程&#xff0c;并发和多线程中的几个问题。 实际上&#xff0c;这种内置的并发支持是Java编程语言的最强优势之一&#xff0c;并帮助它在企业界和程序员中同样流行…

《写给大家看的Web设计书(第3版)》即将上市

《写给大家看的设计书》姊妹篇——《写给大家看的Web设计书&#xff08;第3版&#xff09;》 即将上市。它是Robin Williams的又一本设计书。 也许大家对Robin Williams的畅销书《写给大家看的设计书》还念念不忘&#xff0c;还在回味那些简单凝练的设计经验。那好&#xff0c;…

Node_初步了解(4)小爬虫

1 var httprequire(http);2 var cheeriorequire(cheerio);3 var urlhttp://www.cnblogs.com/Lwd-linux/archive/2017/01.html;4 5 //获取6 function filterChapters(html){7 var $cheerio.load(html);8 9 var chapters$(.entrylistItem); 10 11 var courseData[];…

VUE+ElementUI 搭建后台项目(一)

前言 之前有些过移动端的项目搭建的文章&#xff0c;感觉不写个pc端管理系统老感觉少了点什么&#xff0c;最近公司项目比较多&#xff0c;恰巧要做一个申报系统的后台管理系统&#xff0c;鉴于对vue技术栈比较熟悉&#xff0c;所以考虑还是使用vue技术栈来做&#xff1b;看过一…

ES6_入门(3)_顶层对象属性

1 //顶层对象属性&#xff1a;在ES5中&#xff0c;顶层对象的属性与全局变量是等价的.以下代码中&#xff0c;为顶层对象的属性赋值与全局变量的赋值&#xff0c;是同一件事。2 window.a10;3 console.log(window.a);//104 a40;5 console.log(w…

用 .NET 3.5 创建 ToJSON() 扩展方法

今年早些时候&#xff0c;我通过blog介绍了 C# 和 VB 语言的一项新的扩充特性"扩展方法"。 扩展方法让开发者可以向已有的 CLR 类型的公共契约中添加新的方法&#xff0c;而不需要子类化或重新编译原有的类型。通过这种做法&#xff0c;可以使很多有用的应用场景成为…

Java中File的getPath(),getCanonicalPath()和getAbsolutePath()之间的区别

File API在Java中非常重要&#xff0c;因为它使文件系统可以访问Java程序。 尽管Java的文件API丰富&#xff0c;但是使用它们时仍需要了解许多细节。 关于文件路径的常见查询程序员之一是getPath() &#xff0c; getCanonicalPath()和getAbsolutePath()方法之间的区别&#xff…

Docker容器CPU、memory资源限制

背景 在使用 docker 运行容器时&#xff0c;默认的情况下&#xff0c;docker没有对容器进行硬件资源的限制&#xff0c;当一台主机上运行几百个容器&#xff0c;这些容器虽然互相隔离&#xff0c;但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制&…

JS_理解函数参数按值传递

本文是我基于红宝书《Javascript高级程序设计》中的第四章&#xff0c;4.1.3传递参数小节P70&#xff0c;进一步理解javaSript中函数的参数&#xff0c;当传递的参数是对象时的传递方式。 &#xff08;结合资料的个人理解&#xff0c;有不正确的地方&#xff0c;希望大家指出&…