Scala快查手册

这是一份详细的Scala编程指南,涵盖了从语言特性、类库到并发处理等多个方面。文章强调了Scala的速度、易用的数据结构、OOP与FP的结合、动态与静态特性的融合,以及DSL的设计能力。此外,还介绍了Scala与Java的异同、变量定义、基本类型、集合操作、IO和Actor模型等内容,旨在帮助开发者快速理解和掌握Scala。
摘要由CSDN通过智能技术生成

文章目录

引用:http://qiujj.com/static/Scala-Handbook.htm

Scala的向后兼容性没有Java那么谨慎,2.8+相对于2.7有很大变化,本文档针对2.8+

“和别人分享你的知识,那才是永恒之道”——somebody

前言:

这只是份简单的笔记,本不应敝履自珍,但手痒难耐还是写点废话在前面。

书籍浩如烟海,技术方面的书也汗牛充栋,可惜我们的阅读速度和理解力、记忆力太有限,往往费力学懂的知识转眼就变得非常陌生,“博闻强志、过目不忘”者毕竟罕见。对于大部分人来说,即便昔日信手拈来的东西,时间久了也会毫无头绪。所以知识不在于曾经学过多少,而在于你记住并还能运用多少。

“好记性不如烂笔头”——近年来我慢慢习惯把费力学习的东西都做一个笔记,一是在学习的过程中加深印象,毕竟技术学习不同于欣赏娱乐大片和浏览娱乐新闻看个过眼烟云;二是便于学而“时习之”,书上的东西一般是针对不同技术背景的读者,有很多作者费力用墨之处对你来说纯属废话,而他一笔带过的地方恰恰让你困惑不已。一本读书笔记相当于你对书的“注解”。

Scala很好玩很有趣,但绝对不是一门简单易懂的编程语言(Java从1.0到7.0,一直做++;而Scala不光做++,也做–)。对于从Java或者其他FP走过来的人,Scala有很多“别扭”的用法,很难记清楚用正确。学Scala,最佳的做法是把它用到日常的应用开发中,不断加深记忆。但即便你准备这么做了,手头没有一份方便的备查材料,刚开始也会步履艰难。我在使用的过程中也有这个体会,所以才不怨其烦地把一些学来并尝试过的东西记在本文档中备查,以便之后能行云流水地“玩转”它。整个写笔记的过程,没有孤寂,而是沉浸在学习新知的兴奋和快意中,希望这种快乐也能放大传递给更多的人。

个人认为,对于一门编程语言使用中的查阅,大致有几个阶段:查教程(tutorial)——》查手册(handbook)——》查自己写的库。这个材料,不是严格的教程,或手册,而是介于这两者间。Scala目前已经出版了几本书,这些书从各自的角度解读Scala,比如Scala作者的“Programming Scala”,应该是最权威的Scala书。但好书不一定好读,一是太厚,二是无趣,不如自制的来得贴心。正如数学问题要用公式表达最清楚,编程问题得用图表和代码表示才最清楚,这二者也是本文中使用最多的表达方式,我尽量采用简短的代码来说明问题(简短代码也能说明很多事情,广受赞誉的Effective Java基本没有超过一页的程序代码)。能够熟练使用Java的程序员,参考本笔记,应该可以自如地开始着手写Scala程序。

若能给同样对Scala感兴趣的IT人一些帮助,本人必感欣慰。

——JamesQiu

1. Scala有多cool

“Put productivity & creativity back in the hands of developers”
Scala is a tour de force of language design.

1.1. 速度!

Java的运行速度

——基于JVM,和Java运行速度相当。看看Ruby、Perl、Python对大项目运行效率的无奈,就知道有个好的编译器(Scalac)和运行时(JVM)是多么美好。

Python/Ruby的编程速度

——有更多的内建库和数据结构,编程就更快,Scala在完全继承Java和.NET的标准库的基础上,还扩展了更丰富有用的函数库。看看C++、D、Go等语言库的发展情况(不是匮乏就是混乱),就知道从头创建如Java、.NET这般庞大全面的类库并非易事;

类库和运行速度有关系吗?——很大程度上有,众多专家已经在类库中准备了充分优化的稳定算法,Scala对Java Collection算法进行直接包装或者直接调用,如果没有丰富的类库,你在项目周期内免不了摘抄一些不一定靠谱的算法和功能代码,这些代码极有可能在运行时给你带来麻烦。使用类库算法,不用担忧自造轮子的运行效率。

Scala是静态语言,Scalac和Javac是同一作者,编译成.class后运行于JVM平台,近20年那么多大公司投入进行的优化也不是白搭。对于大部分的应用来说,使用Scala不用再顾虑运行速度,它可能不是最快,但至少逼近Java,而不像Groovy、JRuby、Jython那般与Java有高达数十倍的效率差距。

1.2. 易用的数据结构

List-Map-Tuple及其丰富特性支持让你解决数据结构问题时游刃有余。

List(1,31,4,3,53,4,234) filter (10<) filter (100>)  // List(31, 53)
val (a,b) = List(1, 31,4,3,53,4,234) partition (10>) // a=List(1,4,3,4), b=List(31,53,234)
def info(p:Person) = (name, age, email) // info._1, info._2, info._3

1.3. OOP+FP

  • 适当地选用OOP或者FP,能够使表达相对另一种更加清晰准确。
  • 实际可见的生产力在于:一个应用中的部分代码尤其是高知识凝聚的代码如数学函数和设计模式,一般来说不会自己编写,而是会来自于现成的Java库,或者其他语言,或者伪代码。我们可以很容易地把过程语言、面向对象语言、函数式语言中的代码“翻译”成Scala代码。试想如果我们要把Haskell或者Lisp的某个尾递归算法翻译成Java代码,还得多花点时间;而要把C++的代码翻译成Hashkell,同样也不简单。Scala的混血性给我们的实际使用提供了便利。
  • 语言特色能够塑造编程者的思维: C++也能使用抽象基类设计多重继承,但Java的接口引导你走得更远;Java也能设计类型安全的静态方法(final static),但Scala鼓励你这样做并逐步从OOP到达FP的彼岸,而且来去自如。

1.4. 动态+静态

Scala虽然是一门彻头彻底的静态语言,但又具备了现代动态语言的很多方便和灵活:

  • 不需要冗余的类型声明
  • 可以在已有类上增加新方法(implicit转换和Dynamic trait)
  • 可以把不继承共同父类的不同类型对象传到方法中
  • 可以做静态语言的Refactoring
  • 不用象动态语言那样测试代码比业务代码还多
  • 代码自动完成(REPL和IDE)
  • 编译静态语言的性能
  • Read-Eval-Print Loop交互解释器(注:Linux下的用户体验远好于Windows下)

1.5. DSL

Scala可以把xml/html处理、数学公式表达、SQL查询等包装的更优雅、更合理,为使用者提供更好的API。这也使Scala的程序也更可读,从而更易于维护。

1.6. 够复杂

不同的思考模式:Java是先写后想,Scala是先想后写(其实FP大都如此)。

Scala相比于Java,可能达不到10倍的代码精简;但读Scala代码的效率一般只有Java的1/10——可见Java是一门没有多少特例的简单语言,而Scala则不然。

你不要指望把Scala作为初学者的第一门编程语言,这门语言甚至不是初级程序员能够掌控的——换句话说,能够读懂和写Scala代码,说明你是一个不折不扣的资深程序员,或者更准确一点,是资深Java程序员。

img img
img imgð img img
简单的Java(Morse码,定型的玩具车) 复杂的Scala(智能机,乐高积木)

1.7. 够有趣

还看这句话:“Put productivity & creativity back in the hands of developers”。其实不仅限于Scala,对于所有的编程语言来说,一门语言是否“好玩”有趣,能否激起创作欲,才是最关键的,这比语言风格、运行速度、工具支持、社区文化都来得重要。

回想我使用过的语言,C、C++,只有在学习“图形学”课程做作业的时候给我“好玩”和编程过瘾的感觉;VB、Delphi、Lotus Script/Formular、JavaScript,重来没有给过我“好玩”的感觉,而Java是在之前很长一段时间内让我觉得最“好玩”的语言,用它编游戏、做模式识别的作业、做产品……,乐在其中。但是Java也许久没有再给我这种编程过瘾的感觉了。之前发现Groovy的时候,我以为又找到一门好玩的语言了,但我一段时间使用之后,发现不是我的菜(Perl、Python、Ruby也如此);我不是说那些我不觉得好玩的语言不好,有其他很多人觉得他们非常“好玩”,并且用它们创建了无数杀手级的、伟大的、有用的程序。

有些人对一门语言会玩一辈子,就像Lisp、Haskell和Smalltalk的拥趸;而有些人会不断寻找下一个玩意儿,就像原来玩Java的一些人发现更好玩的Ruby和Python之后,倒戈狂喷Java,力挺后者;Groovy/Grails的玩家在很短的时间里面,写了无数的扩展和Plugin应用;学习Scala,能很多好玩的地方,能用它有激情地去写一些振奋人心的应用出来!

1.8. 开发社区

Scala开发/用户社区气氛良好,基本都是资深开发者以及有一定经验的用户,不会碰到太弱智的事(提问、争吵),除了语言和工具开源免费,最权威和最好的书也都是免费的(包括Lift社区)

2. lang

2.1. 和Java的异同

2.1.1. 语法

Java++:增加的语法 Java–:删减的语法
纯OO 静态成员
操作符重载 原生数据类型
closure break、continue
使用trait进行mixin组合 接口
existential type(_) 通配符List<?>, import pkg.*;
抽象类型 (type T) 原始类型 class C1 {…}
模式匹配 enum枚举

注:

existential type——和Java互操作时进行对应

Iterator<? extends Component> --> Iterator[T] { type T <: Component }或者Iterator[_]

2.1.2. 库

以下功能通过库的形式提供:

  • assert
  • enum
  • property
  • event
  • actor
  • resource control(自动释放)
def using[T <: { def close() }] (res:T)(block:T=>Unit) = {

  try { block(res) } finally { if(res!=null) res.close }}

using (new BufferedReader(new FileReader(path))) { f=> println(f.readLine) }

不用每次使用Java中的finally

val f = new BufferedReader(new FileReader(path)

try { println(f.readLine) } finally { if (f!=null) f.close }

  • query

2.2. 变量

2.2.1. 保留字

abstract case catch class def

do else extends false final

finally for if implicit import

match new null object override

package private protected requires return

sealed super this throw trait

try true type val var

while with yield

_ : = => <- <: <% >: # @

Scala调用Java的方法时,会碰到有Scala的保留字,如Thread.yield()

这在Scala中是非法的,专门有个解决办法,写成: Thread.yield()

注意:没有break和continue

2.2.2. 变量标识

这些标识在Java中是非法的,在Scala中是合法的,可以当作函数名使用,使接口更加DSL:

val empty_? = true

val + = "hello"

val yield = 10

val ** = "power"

2.2.3. 变量定义

2.2.3.1 val, var

var 可变,可重新赋值,赋值为"_"表示缺省值(0, false, null),例如:

var d:Double = _      // d = 0.0

var i:Int = _               // i = 0

var s:String = _        // s = null

var t:T = _                 // 泛型T对应的默认值

val 不可变,相当于const/final,但如果val为数组或者List,val的元素可以赋值;

val pi = 3.            // 相当于3.0d

val pi = 3.f          // 相当于3.0f

提示:向函数式风格推进的一个方式,就是尝试不用任何var来定义变量。

2.2.3.2 花样定义

和Python一样方便的赋值方式:

val x,y = 0                // 赋同一初始值

val (x,y) = (10, "hello")        // 同时定义多个变量,注意:val x,y=10,"hello" 是错误的

更花:

val x::y = List(1,2,3,4)             // x = 1, y = List(2,3,4)

val List(a,b,c) = List(1,2,3)       // a = 1, b = 2, c = 3

进一步花样:

val Array(a, b, _, _, c @ _*) = Array(1, 2, 3, 4, 5, 6, 7)  // 也可以用List,Seq

a // 1

b // 2

c // Array(5, 6, 7), _*匹配0个到多个

使用正则表达式定义:

val regex = "(\d+)/(\d+)/(\d+)".r

val regex(year, month, day) = "2010/1/13"

// year: String = 2010

// month: String = 1

// day: String = 13
2.2.3.3 lazy, val, def的区别
val 定义时就一次求值完成,保持不变 val f = 10+20 // 30
lazy 定义时不求值,第一次使用时完成求值,保持不变 lazy f = 10+20 // f // 30
def 定义时不求值,每次使用时都重新求值 def f = 10+20 // 30def t = System. currentTimeMillis // 每次不一样
scala> val f1 = System.currentTimeMillis

f1: Long = 1279682740376                     // 马上求值

scala> f1

res94: Long = 1279682740376              // 之后保持不变

scala> lazy val f2 = System.currentTimeMillis

f2: Long = <lazy>                                    // 定义时不求值

scala> System.currentTimeMillis

res95: Long = 1279682764297

scala> f2

res96: Long = 1279682766545              // 第一次使用时求值,注意:6545 > 4297

scala> f2

res97: Long = 1279682766545             // 之后保持不变

scala> def f3 = System.currentTimeMillis

f3: Long

scala> f3

res98: Long = 1279682784478             // 每次求值

scala> f3

res99: Long = 1279682785352            // 每次求值

2.3. 基本类型

尽量使用大写形式: Int, Long, Double, Byte, Short, Char, Float, Double, Boolean

编译时Scala自动对应到Java原始类型,提高运行效率。Unit对应java的void

用 asInstanseOf[T]方法来强制转换类型:

def i = 10.asInstanceOf[Double]                                  // i: Double = 10.0

List('A','B','C').map(c=>(c+32).asInstanceOf[Char])       // List('a','b','c')

用isInstanceOf[T]方法来判断类型:

val b = 10.isInstanceOf[Int]                             // true

而在match … case 中可以直接判断而不用此方法。

用Any统一了原生类型和引用类型。

img

2.3.1. Int

-3 abs                                    // 3

-3 max -2                                 // -2

-3 min -2                                // -3

1.4 round                                // 1 四舍五入

1.6 round                                // 2 四舍五入

1.1 ceil                                 // 2.0 天花板

1.1 floor                               // 1.0 地板

无++,–操作,但可以+=, -=, 如下:

var i = 0

i++                    // 报错,无此操作

i+=1                 // 1

i--                    // 报错,无此操作

i-=1                // 0

def even(n:Int) = 0==(n & 1)

def odd(n:Int) = !even(n)

2.3.2. Char

String可以转化为List[Char]

在String上做循环,其实就是对String中的每一个Char做操作,如:

"12345" map (toInt)                    // (49,50,51,52,53)

"jamesqiu" max                          // 'u'

"jamesqiu" min                           // 'a'

('a' to 'f') map (_.toString*3)      // (aaa, bbb, ccc, ddd, eee, fff)

2.4. BigInt

可以表示很大的整数:

BigInt(10000000000000000000000000)          // 报错

BigInt("10000000000000000000000000")       // scala.math.BigInt = 10000000000000000000000000

例如:

def  fac(n:Int):BigInt = if (n==0) 1 else fac(n-1)*n

fac(1000)

或者写成:

def fac2(n:Int) = ((1:BigInt) to n).product
// res1: BigInt = 9332621544394415268169923885626670049071596826438......000000000000000000

2.5. 字符串

“…” 或者 “”"…""""

println("""|Welcome to Ultamix 3000.  

           |Type "HELP" for help.""".stripMargin)

输出:

Welcome to Ultamix 3000.

Type “HELP” for help.

scala中,字符串除了可以+,也可以*

"abc" * 3                                                    // "abcabcabc"

"abc" * 0                                                     // ""

例子:

"google".reverse                                       // "elgoog"

"abc".reverse.reverse=="abc"                          // true

例子:

"Hello" map (_.toUpper)                          // 相当于 "Hello".toUpperCase

2.5.1. 类型转换

"101".toInt                                                 // 101,无需 Integer.parseInt("101");

"3.14".toFloat                                            // 3.14f

101.toString

3.14.toString

转换整个列表:

List("1","2","3") map (_.toInt)                    // List(1,2,3)

或者

List("1","2","3") map Integer.parseInt            // List(1,2,3)

2.5.2. StringBuilder

val sb = new StringBuilder

sb += 'H'

sb ++= "ello"

sb.toString        // "Hello"

sb clear          // StringBuilder()

2.5.3. 文本格式化

使用java.text.MessageFormat.format:

val msg = java.text.MessageFormat.format(
     "At {1,time} on {1,date}, there was {2} on planet {0}.",
      "Hoth", new java.util.Date(), "a disturbance in the Force")

输出

At 17:50:34 on 2010-7-20, there was a disturbance in the Force on planet Hoth.

方法2:

"my name is %s, age is %d." format ("james", 30)          // my name is james, age is 30.

注意:format还可以这么用

"%s-%d:%1s is %2d." format ("james", 30)                 // james-30:james is 30.

"%2d age's man %1s: %2$d" format ("james", 30)           // 30 age's man james: 30

2.6. Null, None, Nil, Nothing

Null Trait,其唯一实例为null,是AnyRef的子类,不是 AnyVal的子类
Nothing Trait,所有类型(包括AnyRef和AnyVal)的子类,没有实例
None Option的两个子类之一,另一个是Some,用于安全的函数返回值
Unit 无返回值的函数的类型,和java的void对应
Nil 长度为0的List

2.7. ==和eq

Scala的很智能,他知道对于数值类型要调用Java中的,ref类型要调用Java的equals()

"hello"=="Hello".toLowerCase()

在java中为false,在scala中为true

Scala的==总是内容对比

基本类型Int,Double, 比值
其他类型 相当于A.equals(B)

eq才是引用对比

例如:

val s1,s2 = "hello"

val s3 = new String("hello")

s1==s2            // true

s1 eq s2          // true

s1==s3              // true 值相同

s1 eq s3             // false 不是同一个引用

2.8. Option[T]

2.8.1. 概念

  • Option[T]可以是任意类型或者空,但一旦声明类型就不能改变;
  • Option[T]可完美替代Java中的null,可以是Some[T]或者None;
  • Option实现了map, flatMap, and filter 接口,允许在 'for’循环里使用它;

函数返回值能被统一处理了:

没有Option的日子 现在
def find(id:Long):Person = … def find(id:Long):Option[Person] = …
返回Person或者null 返回Some[Person]或者None
返回null不特殊处理会抛:NullPointerExceptions 返回值直接getOrElse或者列表操作
类比:Java的Stringx.split返回null 类比:Java的Stringx.split返回new String[0]
结论:函数永远不要返回null值,如果输入有问题或者抛异常,返回Option[T]

参数有效性检查没有那么烦人了:

没有Option的日子 现在
def blank(s:String) = if (s==null) false else { s.toList.forall(_.isWhitespace) } def blank(s:String) = Option(s).toList.forall(.forall(.isWhitespace))
结论:尽可能地不要浪费代码去检测输入,包装成Option[T]来统一处理

2.8.2. 使用

Some(3).getOrElse(4)                               // 3

None.getOrElse4)                                    // 4

例如打印key=3的value:

写法1:

def p(map:Map[Int,Int]) = println(map(3))

p(Map(1->100,2->200))                            // 抛异常

写法2:

def p(map:Map[Int,Int]) = println(map get 3 getOrElse "...")

p(Map(1->100,2->200))                              // ...

p(Map(1->100,3->300))                             // 300

2.8.3. 例子

例子1:

  def m(k:Int) = {

    Map((1,100),(2,200),(3,300)) get(k) match {

      case Some(v) =>

        k + ": " + v

      case None =>

        "not found"

    }

  }

 

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

    println(m(1))     // 100

    println(m(2))     // 200

    println(m(3))     // 300

    println(m(4))    // "not found"

    println(m(-1))    // "not found"

  }

例子2:

val l = List(Some(100), None, Some(200), Some(120), None)

for (Some(s) <- l) yield s // List(100, 200, 120)

l.flatMap (x=>x) // List(100, 200, 120)

例子3: Option结合flatMap

def toint(s:String) =

try { Some(Integer.parseInt(s)) } catch { case e:Exception => None }

List("123", "12a", "45") flatMap toint // List(123, 45)

List("123", "12a", "45") map toint // List(Some(123), None, Some(45))

2.9. 区分<-,=>,->

<- for (i <- 0 until 100) 用于for循环, 符号∈的象形
=> List(1,2,3).map(x=> x*x)((i:Int)=>i*i)(5) // 25 用于匿名函数,相当于Ruby的 |x|,Groovy的{x-> x*x}也可用在import中定义别名:import javax.swing.{JFrame=>jf}
-> Map(1->“a”,2->“b”) 用于Map初始化, 也可以不用->而写成 Map((1,“a”),(2,“b”))

2.10. match…case(switch)

2.10.1. 和switch…case的区别

Java里面的写法:

switch(n) {
   

    case(1): ...; break;

    case(2): ...; break;

    default: ...;

}

变成Scala写法:

def m(n:String) =

n match {

    case "a" | "b" => ... // 这个比较好

    case "c" => ...

    case _ => ...

}

每个case…=>结束不用写break了,_相当于default

2.10.2. 匹配数据类型

match 可以很简单地匹配数据类型(不需要isInstanceOf[T]):

def f(v:Any) = v match {

    case null => "null"

    case i:Int => i*100

    case s:String => s

    case _ => "others"

}

注意:上面case中的i、s都叫模式变量

f(null)          // "null"

f(5)              // 500

f("hello")   // "hello"

f(3.14)      // "others"

注意:自定义类型如果也要匹配,需要用case class

2.10.3. 命令行参数解析例子

/** Basic command line parsing. */
object Main {
  var verbose = false  // 记录标识,以便能同时对-h和-v做出响应
 
  def main(args: Array[String]) {
    for (a <- args) a match {
      case "-h" | "-help"    =>
        println("Usage: scala Main [-help|-verbose]")
      case "-v" | "-verbose" =>
        verbose = true
      case x => // 这里x是临时变量
        println("Unknown option: '" + x + "'")
    }
    if (verbose) println("How are you today?")
  }
}

2.10.4. 使用case的递归函数

写法1:

def fac(n:Int):Int = n match {

  case 0=>1

  case _=>n*fac(n-1)

}

写法2(使用映射式函数):

def fac: Int=>Int = {

    case 0=> 1

    case n=> n*fac(n-1)

}

写法3(使用尾递归):

 def fac: (Int,Int)=>Int = {
    case (0,y) => y
    case (x,y) => fac(x-1, x*y)
  }

fac(5,1) // 120

写法4(reduceLeft+!):

def fac(n:Int) = 1 to n reduceLeft(_*_)
implicit def foo(n:Int) = new { def ! = fac(n) }
5!      // 120

写法5:(最简洁高效)

def fac(n:Int) = (1:BigInt) to n product
fac(5) // 120

2.10.5. 变量匹配

常量匹配很简单,即case后跟的都是常量;变量匹配需要注意,case后跟的是match里面的临时变量,而不是其他变量名:

3 match {
case i => println("i=" + i) // 这里i是模式变量(临时变量),就是3
}
val a = 10
20 match { case a => 1 } // 1, a是模式变量,不是10

为了使用变量a,必须用`a`:

20 match { case `a` => 1; case b => -1 } // -1,`a`是变量10

或者用大写的变量:

val A = 10
20 match { case A => 1; case b => -1 } // -1,大写A是变量10

2.10.6. case…if条件匹配

写法1:

(1 to 20) foreach {                          

    case x if (x % 15 == 0) => printf("%2d:15n\n",x)

    case x if (x % 3 == 0)  => printf("%2d:3n\n",x)

    case x if (x % 5 == 0)  => printf("%2d:5n\n",x)

    case x => printf("%2d\n",x)                          

}

写法2:

(1 to 20) map (x=> (x%3,x%5) match {
  case (0,0) => printf("%2d:15n\n",x)
  case (0,_) => printf("%2d:3n\n",x)
  case (_,0) => printf("%2d:5n\n",x)
  case (_,_) => printf("%2d\n",x)
})

2.11. try…catch…finally

var f = openFile()

try {

  f = new FileReader("input.txt")

} catch {

  case ex: FileNotFoundException => // Handle missing file

  case ex: IOException => // Handle other I/O error

} finally {

  f.close()

}

2.12. require

def f(n:Int) = { require(n!=0); 1.0/n }

def f(n:Int) = { require(n!=0, "n can't be zero"); 1.0/n }

f(0)

// java.lang.IllegalArgumentException: requirement failed: n can't be zero

2.13. main方法

Scala的main方法(包括所有类似java的static方法)必须定义在一个object内:

object Test1 {

    def main(args: Array[String]) {

       println("hello world")

    }

}

编译:

fsc Test1.scala // 常驻内存编译服务器,第一次转载之后比scalac快

运行:

scala Test1.scala // 方式1,没有输出

scala -cp e:\scala\lib\scala-library.jar Test1 // 方式2,慢

java -cp e:\scala\lib\scala-library.jar Test1 // 方式3,快

如果文件不是utf8编码,执行需要使用.scala文件的编码,如:

scala -encoding gbk test.scala

2.13.1. Application

不带命令行参数的简化main方法:

object app1 extends Application {

    println("hello world")

}

2.14. package, import

2.14.1. import

Scala的import可以只在局部作用域内生效;

可以格式 “import javax.swing.{JFrame=>jf}”来声明类型的别名。

jf.show()

  • import javax.swing._
  • import java.util.{List, Map}
  • import java.util., java.io.

Scala 缺省导入如下包:

  • java.lang.*
  • scala.*
  • scala.Predef

由于Scala的package可以是相对路径下定义,有可能命名冲突,可以用:

import root.java.lang.Long

2.14.2. package

package com.wr3 { // C# 和Ruby的方式,也可以改用Java的方式

    // import java.nio._ // "*" 是scala的正常函数名,所以用_

    class c1 {

       def m1() { println("c1.m1()") }

    }

 

    object o1 {

       def main(args: Array[String]) {

          println("o1.main()")

          new c1().m1()

        }

    }

}

编译:

fsc package.scala

运行:

java com.wr3.o1 // 方式1

scala com.wr3.o1 // 方式2

2.14.3. 包对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值