经过几天的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,一经查实,立即删除!

相关文章

检查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属性是否存在全局验证错误。 自…

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…

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;…

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

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

用 .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;希望大家指出&…

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

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

CSS_选择符

2016-10-28 《CSS入门经典》第五章 以下提示注意事项&#xff1a; 1.如何选择使用id选择符还是class选择符&#xff1a;当确信id选择符在页面的唯一性时&#xff0c;就可以使用id选择符。 2.通用选择符在所有元素上设置样式&#xff0c;并不是只设置继承的默认值。 eg&…

TFS2010配置SQLServer2008R2 tf255049错误

TFS2010配置SQLServer2008R2时&#xff0c;配置数据库时提示 tf255049错误。转载于:https://www.cnblogs.com/ShuaiHo/archive/2010/05/12/1733731.html

位运算笔记2.0

声明&#xff1a; 本文为转载文章 转载于:https://www.cnblogs.com/ShineEternal/p/10853132.html

教程–带有Jersey和Spring的Java REST API设计和实现

想要在Java中使用REST&#xff1f; 然后您来对地方了&#xff0c;因为在博客文章中&#xff0c;我将向您介绍如何“美丽”地设计REST API&#xff0c;以及如何使用Jersey框架在Java中实现它。 在本教程中开发的RESTful API将为存储在MySql数据库中的播客资源演示完整的Create&a…

ie6 下最佳 PNG透明方案【转】

“咳! 哎!….. ” 你听见了么? 这些都是大家抱怨IE6下不能实现png图片漂亮的明效果的哀叫声,的确是无奈呀….. 不过现在幸运的是,我们能够让这一切的抱怨都停止. 网络上解决IE6下Png透明解决方案有很多,例如 IE PNG Fix from TwinHelix, Javascript IE PNG Fix, Transparent …

安装svn、git等托管软件

安装软件&#xff0c;配置环境。下面我找到的别人写的&#xff0c;写的都很详细&#xff0c;做个记录。就不在这里写具体步骤了。 1.nodejs安装 使用vue-cli 搭建项目的时候需要nodejs&#xff0c;node是比较方便的&#xff0c;打包部署&#xff0c;解析vue单文件组件&#xff…