自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Scala初學者學習資料:main(String[])

開發(fā) 后端
本文是一位美國開發(fā)者在08年初寫的Scala學習筆記的第一部分,講述Scala中的一些基礎知識,尤其是main(String[])的用法。

51CTO編輯推薦:Scala編程語言專題

你可能已經使用JAVA若干年了,或許JAVA是你接觸編程來的***門編程語言,或許是作為比C++更好的一個選擇。不管怎么樣,你已經適應了JAVA,并了解她的外觀與內在,能夠體會它的喜怒與哀樂(原文:You’re comfortable with Java, you know its ins and outs, its moods)。她就像你相處多年的女朋友,或許剛相識時那種激情已經不再,但你已經熟悉怎樣才能讓她開心。簡單的說,如果你是一位工匠,則JAVA就是你干活的工具。

然而,你和JAVA的蜜月期過去了,你在編程語言的選擇上更加務實了。只要有足夠的理由,你就可以毫不猶豫去嘗試一種新的語言,但JAVA還沒有足夠的缺陷讓你下定決心離開她。此時,你聽說了一個叫做Ruby的東東,它的簡潔優(yōu)雅以及巨大的威力給你留下深刻的印象。但你并不是那么確定去使用一個腳步語言來構建你的企業(yè)應用。動態(tài)類型以及TextMate確實都不錯,但對于現實世界,你需要一個更堅實的支柱。作為一個實用主義者,你仍然堅持使用JAVA。

這時,好消息傳來了。一門新的編程語言登上了舞臺并在開發(fā)者的世界引起了一場風暴。Scala貌似具有你對一門編程語言所期待一切: 靜態(tài)類型,編譯為字節(jié)碼,簡潔且富有表現力的語法。你可能已經被它的一些例子給深深吸引了。它看起來和JAVA非常相似,但是剔除了JAVA中冗余的語法結構。Scala沒有分號,沒有public static void的方法修飾詞,并且具有靜態(tài)類型推斷機制。

現在剩下的唯一問題就是你應該從何開始。你也許嘗試過去Scala的網站查看相關知識,但是。。這一切看起來是那么的函數化:Lamdas,high-order functions,immutable state,recursion out the wazoo。突然讓人感到前途未卜。

但是,JavaEE的難民們,不必擔心。Scala確實是一門函數式的編程語言,但它同樣也是命令式的和面向對象的。也就是說,除了書寫那種晦澀難懂的函數式代碼(原文: It means that you don’t have to write code with the sole purpose of pleasing Haskell Curry),你還有其它的選擇。你可以書寫可讀性很強的代碼,以便你一個星期之后還能看懂它。將你的代碼給你那些只使用JAVA的同事看,他們甚至也能看懂它。只需要一個正確的引導,你就可以使用Scala來構建你的的JAVA應用。

導讀:

如果符合上面所說的,那么這個Scala系列就是為你而準備的。我已經閱讀過大量有關Scala的文章以及入門材料(如果你更喜歡函數式的編程,我強烈推薦你去看Alex Blewitt寫的系列文章),但很少有文章是為了使JAVA開發(fā)比較輕松的轉變到Scala來的。我個人缺乏FP(函數式編程)的經驗,因此我肯定不會在文章中介紹如何將Scheme代碼移植到Scala。該系列文章著重于類比Scala與JAVA,并說明為什么Scala比JAVA更好。

起步:

  1. object HelloWorld extends Application{  
  2.     println("Hello, World!")  

沒有什么比用代碼來獲得知識更直接了,注意到上面的代碼沒有使用分號。當然,如果你愿意還是可以像在JAVA中一樣使用它。但除非你想在同一行中書寫多個語句,否則分號不是必須的。這個代碼示例含義非常清楚,想必你已經看明白了它的功能。沒錯,就是向標準控制臺輸出一行"Hello, World!"。你可以將這些代碼保存到一個后綴名為scala的文件中,然后使用scala編譯器編譯它,編譯的結果是一個單獨的class文件(譯者注:這里原文似乎有錯,我編譯后事實上生成了兩個class文件)。你可以像運行普通java文件那樣使用java解釋器來運行它,不過你需要注意一下classpath。最直接的方法是使用scala命令:

  1. scalac hello.scala   
  2. scala HelloWorld 

注意到"hello.scala"文件名沒有?Scala并不像Java一樣強制你在定義public class時,必須保存在文件名與類名相同的文件中。事實上Scala允許你像C++或Ruby一樣,在同一個文件中你想定義多少class都可以。但我們***還是遵循Java的命名規(guī)則,因此作為一個具有良好習慣的程序員,我們應該將上面的代碼保存為"HelloWorld.scala"。

編輯器:

在剛開始接觸Scala,選擇一個正確的編輯器是個關鍵。就像你在使用Java中所了解的那樣,IDE非常有用。但作為一門新生的編程語言,Scala目前還沒有很好的IDE支持,不過這只是時間問題。在目前,你只有非常有限的選擇:

◆Eclipse(有幾個不太成熟的Scala插件)

◆Emacs

◆IntelliJ(只支持基本的語法高亮)

◆TextMate

◆VIM

◆jEdit

(譯者注:我使用的是UltraEdit,自己配置一下,能夠自動縮進與語法高亮以及編譯運行,湊合著用了)

上面列的是幾個主要的選項,更完整的列表可以去Scala安裝目錄下的misc/scala-tool-support/文件夾下查看。我個人推薦使用jEidt或者TextMate;如果你有冒險精神,可以去嘗試Eclipse上的幾個插件。Eclipse上的插件具有通常IDE所具有的一些功能(至少Beta版是這樣),譬如語義高亮,代碼自動完成,etc。但根據我的經驗,這些插件都不夠穩(wěn)定以至于難以使用。Scala是一門比Java簡潔多的語言,它對IDE的依賴性比Java小得多,因此這些都不是本質問題,你可以照樣做的很好。

再來一個例子

  1. object HelloWorld2{  
  2.     def main(args:Array[String]) = {  
  3.        var greeting ="" 
  4.        for(i <- 0 until args.length){  
  5.            greeting += (args(i) + " ")          
  6.        }  
  7.        if(args.length > 0) greeting =greeting.substring(0, greeting.length -1 )  
  8.          
  9.        println(greeting)  
  10.     }  

(譯者注: 可能有讀者會奇怪greeting += (args(i) + " ")這段代碼為什么要用括號,注意,雖然與習慣不同,但這里的括號是必須的。因為在Scala里面,運算符的優(yōu)先級由運算符***個字符代表的運算符的優(yōu)先級確定。就是說"+="的優(yōu)先級與"+"的優(yōu)先級一樣,然后……自己想吧:-)。BTW,Scala里的運算符也是方法&對象。)

將它保存到HelloWorld2.scala,并使用如下命令編譯運行:

  1. scalac HelloWorld2.scala   
  2. scala HelloWorld2 Hello, World! 

這次我們使用了不同的方式,通過命令行向程序傳遞參數,其運行的結果同樣是在控制臺輸出"Hello, World"。這個程序比上一個復雜一些,首先定義了一個String類型的變量greeting,然后遍歷一個數組,***對String進行適當的處理(Scala專家肯定會建議使用Array#deepMkString(String)(類似于Ruby中的Array::join方法),這樣確實沒錯。但我這里主要是為了介紹一些語言上的知識,而不是API的使用)。

首先應該注意的是,這里我們定義了一個main方法。在***個例子中,我們僅僅繼承了Application類,然后把其它的都交給默認構造函數來做。這樣很好很簡潔,但有兩個問題:***,我們沒有辦法向程序傳遞命令行參數;第二,對Scala新手來說,這樣看起來有點魔幻。我將在后面的文章中揭開***個例子中背后的把戲,現在你記住它就是了。

這個例子中的main方法是不是已經讓你聯想到了JAVA中的 public static void main?沒錯,Scala中的main就對應Java中的 public static void main。根據這個信息,有經驗的程序員就可以通過思考知道更多關于Scala的知識。

一開始,你可能有這樣的結論:Scala中的方法隱含就是public的。這基本正確,Scala中的方法默認為public,這意味著Scala中沒有public方法修飾詞(private與protected都有定義)。更進一步的,你會猜測:Scala中的方法默認為static的。然而,這次你的猜想不完全正確。

Scala并沒有真正意義上的static屬性。你越早認識到這一點,你就越容易理解這門語言。作為替代,Scala有專門的語法讓你實現與使用sigleton模式(這正是object的含義)。我們實際上聲明了一個具有實例方法main(譯者注:注意,這個main方法并不是static的)的單實例類(singleton class)。我將會在以后詳細說明這一點,目前你可以認為object就是一個只具有靜態(tài)方法的類。(譯者注:這個描述不甚準確)。

仔細的觀察這個例子,我們還可以得到Scala中數組的語法,以及如何顯式的指明一個變量的類型。讓我們仔細研究一下聲明main方法的這行代碼:

  1. def main(args:Array[String]) = { 

這兒,args是一個Array[String]類型的方法參數。也就是說,args是一個String數組。在Scala中,Array是一個具有類型參數指明其元素類型的類(一個真正的類,而不是JAVA中那樣)。與之對等的JAVA語法應該類似與下面這樣子(假設Java中也有一個Array類):

  1. public static void main(Array< String> args) 

在Scala中,使用variable:Type的語法來指明變量類型。因此,如果我們想顯式聲明一個Int類型的變量,應該通過如下方式

  1. var myInteger:Int 

在例子中,我們實際上聲明了一個String類型的變量greeting。然而,得益于Scala中的類型推斷機制,我們并沒有顯式指明變量的類型。下面兩種方式在語義上是等價的:

  1. var greeting ="" 
  2.  
  3. var greeting:String ="" 

在***種方式中,我們顯然知道greeting是一個String,Scala編譯器也能夠推斷出這一點。這兩個變量都是靜態(tài)類型檢查的,只不過***種方式可以少寫7個字符:-)

細心的讀者可能還注意到了,例子中的main方法并沒有指明返回類型。這是因為Scala同樣可以推斷出來。如果我們想顯式的指明這點,可以像下面這樣:

  1. def main(args:Array[String]):Unit = { 

如前面一樣,類型在方法名之后,并用冒號隔開。順便提一下,Unit是Scala中的一個類型,它表示"我不關心返回的究竟是什么東東"(原文:I-really-don't-care-what-I-return),你可以把它想象為JAVA中void類型與對象的混合物(譯者注:但Unit不是void,而是一個實實在在的類,也就是說Unit類型的方法會返回一個Unit對象)。

數組的遍歷:

  1. var greeting ="" 
  2. for(i <- 0 until args.length) {  
  3.     greeting += (args(i) + " ")  
  4. }  

(譯者注: 目前Scala中這種方式遍歷的性能相對低下,速度大概是JAVA中對應for的1/60。這個其實也不會造成太大的影響,因為耗時一般不在于for循環(huán)本身,而是循環(huán)體內的操作。更何況在Scala中用for的機會不多,有更多簡單實用的方式去實現同樣的操作)

這段代碼比剛才那段稍微復雜點。我們一開始聲明了一個String類型的變量greeting,然后使用了一個在Scala中不常用的for循環(huán),這里有一些隱含的類型推斷。有Ruby經驗的知道在Ruby中的等價形式:

  1. for i in 0..(args.size - 1)  
  2.   greeting += args[i] + " " 
  3. end 

問題的關鍵在于,Scala的for循環(huán)語句需要一個Range對象,而這個Range對象是由RichInt的until方法建立的。我們可以把上面的代碼分開寫:

  1. val range =0.until(args.length)  
  2. for(i <- range) { 

注意,這里使用"val"而不是"var"聲明變量。使用val,就如java中final的語義,指明range是一個常量。

在Scala中,我們可以通過多種不同的形式調用方法。在這個例子中,我們看到了"value methodName param"與"value。methodName(param)"這兩種形式的語法是等價的。另外一個很重要的事情是,until方法是RichInt具有的,Int并沒有該方法。這里存在一個隱式類型轉換,將Int類型的0轉換為scala。runtime。RichInt的一個實例。這里不去深究這個類型轉換是怎樣進行的,我們關心的是RichInt類確實有一個返回Rangle對象的until方法。

因此,事實上這段代碼與JAVA中的下列代碼在邏輯上是等價的:

  1. for (int i = 0; i < args.length; i++) { 

只不過在JAVA中是顯式的遍歷整個區(qū)間,而Scala中使用了一個Range對象。

可能你還注意到了,循環(huán)體中訪問數組args元素使用的是圓括號"()",而不是我們習慣的方括號"[]"。

更好的遍歷方式:

在JAVA 5中引入了一個foreach的語法,像下面這樣:

  1. for(String arg: args) {  
  2.     greeting += arg + " ";  

這樣更簡潔明了。Scala中使用高階函數(使用函數做參數的函數)實現類似的功能:

  1. args.foreach {arg =>  
  2.     greeting += (arg + " ")  

我們可以看到,Array類有一個foreach方法,這個方法將一個函數作為參數。foreach方法將會對Array里的每一個元素調用一次這個函數,并在調用的時候將這個元素作為函數參數傳遞給函數。這里參數arg沒有指明類型,但由于我們是對一個String數組遍歷,編譯器能推斷出它的類型是String。我們已經提到過,Scala中調用方法有多鐘不同的方式。這里我們就省略了圓括號"()",同樣我們也可以寫成:

  1. args.foreach(arg => {  
  2.   greeting += (arg + " ")  
  3. }) 

Scala中我們可以使用更加簡潔的書寫方式:

  1. args.foreach(arg => greeting +=(arg + " ")) 

不錯吧,現在我們將整個例子重寫成:

  1. object HelloWorld2 {  
  2.   def main(args:Array[String]) = {  
  3.     var greeting = "" 
  4.     args.foreach(arg => greeting += (arg + " "))  
  5.     if (args.length > 0) greeting = greeting.substring(0, greeting.length - 1)  
  6.    
  7.     println(greeting)  
  8.   }  

Scala的內置類型:

因為Scala是基于JVM的,因此它從JAVA那兒繼承了大量的API。這意味這你能夠與JAVA交互使用。并且,你所寫的Scala代碼事實上使用的就是Java API。比如上面的HelloWorld2中我們使用了一個字符串變量greeting,這個變量事實上就是Java中的String類型。再比如,當你在Scala中聲明一個整數類型(Int),編譯器會自動將它轉換為Java的基本類型int。

Scala還內置了一些隱式類型轉換,當需要的時候編譯器會自動進行(就像例子中的Int到RichInt類型的轉換)。比如在Scala中將Array[String]類型傳遞給需要String[]類型參數的函數時,隱式類型轉換就會發(fā)生。甚至Scala中的類型參數可以和Java中的泛型相互轉化。簡單的說,Scala就是一個披著不同語法外衣的Java。

結束

Scala不需要復雜高深的理論或學術知識。一個普通的開發(fā)者就可以在下一個企業(yè)WEB應用里面使用它。它具有JAVA所缺乏的簡潔明了的語法,并且保留了JAVA的高效與可靠性。

【相關閱讀】

  1. Scala創(chuàng)始人致信51CTO:全面解答Scala的泛型優(yōu)勢
  2. Scala的類型系統(tǒng):取代復雜的通配符
  3. Scala的類型系統(tǒng) 比Java更靈活
  4. Java程序員,你為什么要關注Scala
  5. Scala編程語言
責任編輯:yangsai 來源: JavaEye博客
相關推薦

2020-09-08 19:03:41

Java代碼初學者

2015-07-20 13:56:59

SDN

2023-10-14 17:21:53

Scala編程

2009-09-28 09:45:00

CCNA學習經驗CCNA

2011-04-12 10:13:24

2009-09-28 10:34:43

NET初學者學習建議

2011-08-24 17:05:01

Lua

2011-09-16 09:38:19

Emacs

2022-04-24 15:21:01

MarkdownHTML

2021-03-14 18:22:23

套接字網絡通信

2009-11-18 09:30:43

2011-05-18 11:01:39

Oracle

2021-05-10 08:50:32

網絡管理網絡網絡性能

2022-03-28 09:52:42

JavaScript語言

2023-07-28 07:31:52

JavaScriptasyncawait

2023-07-03 15:05:07

預測分析大數據

2009-06-12 15:16:53

Hibernate學習

2009-12-08 09:45:50

調用WCF

2011-07-26 17:55:16

iPhone Runtime

2010-01-15 19:05:42

學習C++
點贊
收藏

51CTO技術棧公眾號