scala最近幾年很火,主要是因為其在大數據領域的應用。
下面這些面試題,基本上是scala函數式編程的精髓。
Q1 var,val和def三個關鍵字之間的區別?
答:var是變量聲明關鍵字,類似於Java中的變量,變量值可以更改,但是變量類型不能更改。 val常量聲明關鍵字。 def 關鍵字用於創建方法(注意方法和函數的區別)
Q2 trait(特質)和abstract class(抽象類)的區別?
答:(1)一個類只能集成一個抽象類,但是可以通過with關鍵字繼承多個特質; (2)抽象類有帶參數的構造函數,特質不行(如 trait t(i:Int){} ,這種聲明是錯誤的)
Q3 object和class的區別?
答:object是類的單例對象,開發人員無需用new關鍵字實例化。如果對象的名稱和類名相同,這個對象就是伴生對象(深入了解請參考問題Q7)
Q4 case class (樣本類)是什么?
答:樣本類是一種不可變且可分解類的語法糖,這個語法糖的意思大概是在構建時,自動實現一些功能。樣本類具有以下特性: (1)自動添加與類名一致的構造函數(這個就是前面提到的伴生對象,通過apply方法實現),即構造對象時,不需要new; (2)樣本類中的參數默認添加val關鍵字,即參數不能修改; (3)默認實現了toString,equals,hashcode,copy等方法; (4)樣本類可以通過==比較兩個對象,並且不在構造方法中定義的屬性不會用在比較上。
Q5 Java和Scala 異步計算的區別?
答:這里作者的意思是他大概也不清楚,請閱讀這個 really clean and simple answer on StackOverflow,我個人理解還不到位后續補上。
Q6 unapply 和apply方法的區別, 以及各自使用場景?
答:先講一個概念——提取器,它實現了構造器相反的效果,構造器從給定的參數創建一個對象,然而提取器卻從對象中提取出構造該對象的參數,scala標准庫預定義了一些提取器,如上面提到的樣本類中,會自動創建一個伴生對象(包含apply和unapply方法)。 為了成為一個提取器,unapply方法需要被伴生對象。 apply方法是為了自動實現樣本類的對象,無需new關鍵字。
Q7 伴生對象是什么?
答:前面已經提到過,伴生對象就是與類名相同的對象,伴生對象可以訪問類中的私有量,類也可以訪問伴生對象中的私有方法,類似於Java類中的靜態方法。伴生對象必須和其對應的類定義在相同的源文件。
Q8 Scala類型系統中Nil, Null, None, Nothing四個類型的區別?
答:Null是一個trait(特質),是所以引用類型AnyRef的一個子類型,null是Null唯一的實例。 Nothing也是一個trait(特質),是所有類型Any(包括值類型和引用類型)的子類型,它不在有子類型,它也沒有實例,實際上為了一個方法拋出異常,通常會設置一個默認返回類型。 Nil代表一個List空類型,等同List[Nothing] None是Option monad的空標識(深入了解請參考問題Q11)
Q9 Unit類型是什么?
答:Unit代表沒有任何意義的值類型,類似於java中的void類型,他是anyval的子類型,僅有一個實例對象"( )"
Q10 call-by-value和call-by-name求值策略的區別?
答:(1)call-by-value是在調用函數之前計算; (2) call-by-name是在需要時計算
Q11 Option類型的定義和使用場景?
答:在Java中,null是一個關鍵字,不是一個對象,當開發者希望返回一個空對象時,卻返回了一個關鍵字,為了解決這個問題,Scala建議開發者返回值是空值時,使用Option類型,在Scala中null是Null的唯一對象,會引起異常,Option則可以避免。Option有兩個子類型,Some和None(空值)
Q12 yield如何工作?
答:yield用於循環迭代中生成新值,yield是comprehensions的一部分,是多個操作(foreach, map, flatMap, filter or withFilter)的composition語法糖。(深入了解請參考問題Q14)
Q13 解釋隱示參數的優先權
答:在Scala中implicit的功能很強大。當編譯器尋找implicits時,如果不注意隱式參數的優先權,可能會引起意外的錯誤。因此編譯器會按順序查找隱式關鍵字。順序如下: (1)當前類聲明的implicits ; (2)導入包中的 implicits; (3)外部域(聲明在外部域的implicts); (4)inheritance (5)package object (6)implicit scope like companion objects
Q14 comprehension(推導式)的語法糖是什么操作?
答:comprehension(推導式)是若干個操作組成的替代語法。如果不用yield關鍵字,comprehension(推導式)可以被forech操作替代,或者被map/flatMap,filter代替。
Q15 Streams:當使用Scala Steams時需要考慮什么?Scala的Streams內部使用什么技術?
答:還沒有理解,暫時不翻譯,后續補上。
Q16 什么是vaule class?
答:開發時經常遇到這個的問題,當你使用integer時,希望它代表一些東西,而不是全部東西,例如,一個integer代表年齡,另一個代表高度。由於上述原因,我們考慮包裹原始類型生成一個新的有意義的類型(如年齡類型和高度類型)。 Value classes 允許開發者安全的增加一個新類型,避免運行時對象分配。有一些 必須進行分配的情況 and 限制,但是基本的思想是:在編譯時,通過使用原始類型替換值類實例,刪除對象分配。
Q17 Option ,Try 和 Either 三者的區別?
答:這三種monads允許我們顯示函數沒有按預期執行的計算結果。 Option表示可選值,它的返回類型是Some(代表返回有效數據)或None(代表返回空值)。 Try類似於Java中的try/catch,如果計算成功,返回Success的實例,如果拋出異常,返回Failure。 Either可以提供一些計算失敗的信息,Either有兩種可能返回類型:預期/正確/成功的 和 錯誤的信息。
Q18 什么是函數柯里化?
答:柯里化技術是一個接受多個參數的函數轉化為接受其中幾個參數的函數。經常被用來處理高階函數。
Q19 什么是尾遞歸?
正常遞歸,每一次遞歸步驟,需要保存信息到堆棧里面,當遞歸步驟很多時,導致堆棧溢出。 尾遞歸就是為了解決上述問題,在尾遞歸中所有的計算都是在遞歸之前調用, 編譯器可以利用這個屬性避免堆棧錯誤,尾遞歸的調用可以使信息不插入堆棧,從而優化尾遞歸。 使用 @tailrec 標簽可使編譯器強制使用尾遞歸。
Q20 什么是高階函數?
答:高階函數指能接受或者返回其他函數的函數,scala中的filter map flatMap函數都能接受其他函數作為參數。