java scala_经过几天的Scala回归Java的10个最烦人的事情
java scala
因此,我正在嘗試使用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具有很大的潛力。
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個屬性,構造函數,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的編譯示例。
注意:警告
允許操作符重載或符號方法名之類的東西總是存在弊端。 它可能(并將被)濫用。 圖書館與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
java scala
總結
以上是生活随笔為你收集整理的java scala_经过几天的Scala回归Java的10个最烦人的事情的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美国作家协会和17位知名作家对OpenA
- 下一篇: java lambda函数_Java S