企业建站1年,创新驱动发展战略纲要,专门做网站制作的公司,网站官网建设方案因此#xff0c;我正在尝试使用Scala#xff0c;因为我想编写一个解析器#xff0c;而Scala Parsers API似乎非常合适。 毕竟#xff0c;我可以在Scala中实现解析器并将其包装在Java接口后面#xff0c;因此除了附加的运行时依赖关系之外#xff0c;不应该存在任何互操作… 因此我正在尝试使用Scala因为我想编写一个解析器而Scala Parsers API似乎非常合适。 毕竟我可以在Scala中实现解析器并将其包装在Java接口后面因此除了附加的运行时依赖关系之外不应该存在任何互操作性问题。 在几天后真正真正地习惯了Scala语法的强大功能之后以下是我回到编写Java时最想错过的十件事 1.多行字符串 这是我个人的最爱也是一种非常棒的功能应该使用任何语言。 甚至PHP都有多行字符串。 就像写作一样简单 println (Dear reader,If we had this feature in Java,
wouldnt 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 1elseprintln(DSL.using(configuration)// Observe this little s.fetch(sSELECT 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)
) 太棒了不是吗 对于SQLScala具有很大的潜力。 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.toString4.类型推断 在Java中这真的很烦人与此同时似乎还有许多其他语言也做到了这一点。 Java仅具有有限的类型推断功能而且事情并不尽如人意 。 在Scala中我可以简单地写 val s myObject.toString ……而不关心s是String类型的事实。 有时但仅在某些情况下我希望明确指定引用的类型。 在那种情况下我仍然可以做到 val s : String myObject.toString5.案例分类 我想我想写另一个POJO它具有40个属性构造函数gettersetterequalshashCode和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 doesnt 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 doesnt 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的编译示例。 注意警告 允许操作符重载或符号方法名之类的东西总是存在缺点。 它可能并将被滥用。 图书馆与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 Tuple2T1, T2 {// Lots of bloat, see missing case classes
}class Tuple3T1, T2, T3 {// Bloat bloat bloat
} 然后 // Yikes, no type inference...
Tuple2Integer, String t1 new Tuple2(1, A);// OK, this will certainly not look nice
Tuple3Integer, String, Tuple2Integer, 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