Scala与Java差异(三)之函数
一、函數定義
(1)函數的定義與調用
在Scala中定義函數時,需要定義函數的函數名、參數、函數體。
第一個函數如下所示:
def sayHello(name: String, age: Int) = {if (age > 18) { printf("hi %s, you are a big boy\n", name); age }else { printf("hi %s, you are a little boy\n", name); age}sayHello("leo", 30)Scala要求必須給出所有參數的類型,但是不一定給出函數返回值的類型,只要右側的函數體中不包含遞歸的語句,Scala就可以自己根據右側的表達式推斷出返回類型。
?(2)在代碼塊中定義包含多行語句的函數體
單行的函數:def sayHello(name: String) = print("Hello, " + name)
如果函數體中有多行代碼,則可以使用代碼塊的方式包裹多行代碼,代碼塊中最后一行的返回值就是整個函數的返回值。與Java中不同,不是使用return返回值的。
比如如下的函數,實現累加的功能:
def sum(n: Int) = {var sum = 0;for(i <- 1 to n) sum += isum }(3)遞歸函數與返回類型
如果在函數體內遞歸調用函數自身,則必須手動給出函數的返回類型。
例如,實現經典的斐波那契數列:
9 + 8; 8 + 7 + 7 + 6; 7 + 6 + 6 + 5 + 6 + 5 + 5 + 4; ....
def fab(n: Int): Int = {if(n <= 1) 1else fab(n - 1) + fab(n - 2)}?
二、函數的默認參數和帶名參數
(1)?默認參數
在Scala中,有時我們調用某些函數時,不希望給出參數的具體值,而希望使用參數自身默認的值,此時就定義在定義函數時使用默認參數。
def sayHello(firstName: String, middleName: String = "William", lastName: String = "Croft") = firstName + " " + middleName + " " + lastName如果給出的參數不夠,則會從作往右依次應用參數。
(2)Java與Scala實現默認參數的區別
Java:
public void sayHello(String name, int age) {if(name == null) {name = "defaultName"}if(age == 0) {age = 18}}sayHello(null, 0)Scala:
def sayHello(name: String, age: Int = 20) {print("Hello, " + name + ", your age is " + age)}sayHello("leo")(3)帶名參數
在調用函數時,也可以不按照函數定義的參數順序來傳遞參數,而是使用帶名參數的方式來傳遞。
sayHello(firstName = "Mick", lastName = "Nina", middleName = "Jack")還可以混合使用未命名參數和帶名參數,但是未命名參數必須排在帶名參數前面。
sayHello("Mick", lastName = "Nina", middleName = "Jack")?
三、函數的變長參數
(1)變長參數
在Scala中,有時我們需要將函數定義為參數個數可變的形式,則此時可以使用變長參數定義函數。
def sum(nums: Int*) = {var res = 0for (num <- nums) res += numres}sum(1, 2, 3, 4, 5)(2)使用序列調用變長參數
在如果想要將一個已有的序列直接調用變長參數函數,是不對的。比如val s = sum(1 to 5)。此時需要使用Scala特殊的語法將參數定義為序列,讓Scala解釋器能夠識別。這種語法非常有用!一定要好好注意,在spark的源碼中大量地使用到了。
val s = sum(1 to 5: _*)案例:使用遞歸函數實現累加
def sum2(nums: Int*): Int = {if (nums.length == 0) 0else nums.head + sum2(nums.tail: _*)?
四、函數的過程、lazy值和異常
(1)過程
在Scala中,定義函數時,如果函數體直接包裹在了花括號里面,而沒有使用=連接,則函數的返回值類型就是Unit。這樣的函數就被稱之為過程。過程通常用于不需要返回值的函數。
過程還有一種寫法,就是將函數的返回值類型定義為Unit。
def sayHello(name: String) = "Hello, " + namedef sayHello(name: String) { print("Hello, " + name); "Hello, " + name }def sayHello(name: String): Unit = "Hello, " + name(2)lazy值
在Scala中,提供了lazy值的特性,也就是說,如果將一個變量聲明為lazy,則只有在第一次使用該變量時,變量對應的表達式才會發生計算。這種特性對于特別耗時的計算操作特別有用,比如打開文件進行IO,進行網絡IO等。
import scala.io.Source._lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString即使文件不存在,也不會報錯,只有第一個使用變量時會報錯,證明了表達式計算的lazy特性。
val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkStringlazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkStringdef lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString(3)?異常
在Scala中,異常處理和捕獲機制與Java是非常相似的。
try {throw new IllegalArgumentException("x should not be negative")} catch {case _: IllegalArgumentException => println("Illegal Argument!")} finally {print("release resources!")} try {throw new IOException("user defined exception")} catch {case e1: IllegalArgumentException => println("illegal argument")case e2: IOException => println("io exception")}?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Scala与Java差异(三)之函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三十而已什么时候上映 电视剧三十而已介绍
- 下一篇: 梦幻西游彩虹怎么玩 梦幻西游彩虹玩法