首页 > 代码库 > scala与java之间的那些事

scala与java之间的那些事

scala与java之间的关系,我认为可以用一句话来开头:scala来源于java,但又高于java。

scala的设计者Martin Odersky就是一个JAVA控,这位牛人设计了javac和编写了jdk中的通用代码。可以说java语言本身就是Martin Odersky一步一步看着长大的。所以scala可以说打根起就和JAVA有着远远悠长的血缘关系。

Martin Odersky还在写java那会,就立志开发达成一个目标:让写程序这样一个基础工作变得高效、简单、且令人愉悦!因此可以说scala是这个目标实现过程中的一个重要里程碑。

因此可以说java是职业装,scala就是休闲服。

scala简练,高效。java成熟,稳重。

但是尺有所长,寸有所短。scala的简练高效有其独有的使用范围:scala最适合用在算法描述领域,java适合用在指令编程领域。

scala独有的两招:函数式编程、简单的并发编程

1、scala独有的函数式编程。

  函数是scala语言中的一等公民。

  一等公民的特权表现在:1.函数可以传递、赋值
             2.scala中有嵌套函数和匿名函数
               3.scala支持高阶函数
             4.scala支持偏应用(偏函数)
             5.scala支持闭包

  举例来说:

  1.可传递
  

 1 def  func(f:()  =>  String)  =  println(f()) 2 func(()  =>  "hi") 3 //output:  hi 4          5 def  foo()  =  "ok" 6 func(foo) 7 //output:  ok 8          9 val  fun  =  (x:Int)  =>  print(x)10 fun(2)11 //output:2

 

  2.嵌套函数

 

1 def foo(){2     def bar(){3         println("hi")4         }5     bar  //exec6 }7 8 foo //output:hi        


嵌套函数在实际中应用场景不多,其中一个场景是将递归函数转为尾递归方式!

 1 def fun1(){ 2   ..... 3   this       4 } 5  6 def fun2(){ 7   .... 8   this 9 }10 11 //两个函数可以如下方式使用12 fun1().fun2()

 

  3.匿名函数

1 lambda:函数字面量(Function literal)2 (x:Int,y:Int) => x +y3 参数 右箭头 函数体4 5 上面语句产生一段匿名函数,类型为(Int,Int) => Int6 注意:scala中函数的参数个数为0到22个

 

 

  4.高阶函数

 

 1 第一种:用函数做参数的函数。eg: 2  3 def f2(f:() => Unit) {f()} 4  5 def f1(){println(1)} 6  7 f2(f1) 8  9 f2(() => println("hi")) //传入匿名函数10 11 第二种:产生的结果是一个函数的函数。eg:12 13 def hf():Int => Int = x => x +114 15 val fun = hf16 17 fun(2) //output:3


  5.函数柯里化

 1 当函数具有多个参数时 2 def sum(x:Int,y:Int) = x + y 3  4 //参数被打散后,两个参数分开 5 def sum2(x:Int)(y:Int) = x + y 6  7 sum2(1)(2) //output:3 8  9 scala> def first(x:Int)=(y:Int) => x+y10 first: (x: Int)Int => Int11 12 scala> first(1)13 res10: Int => Int = <function1>14 15 scala> val second=first(1)16 second: Int => Int = <function1>17 18 scala> second(2)19 res11: Int = 320 21 函数链22 把一个带有多个参数的函数,转换为多个只有一个参数的函数来执行23 24 f(1)(2)(3) 相当于 ((f(1))(2))(3)25 26 带入参数 1执行 fa(1) 然后 带入参数2执行 fb(2) 接着带入参数3执行fc(3) 最后得到结果27 28 柯里化的实际用途?29 控制抽象,可改变代码的书写风格 foo(res,()=>println(res)) foo(res)(()=> println(res)) foo(res){()=> println(res)}30 实现部分应用函数31 scala> def log(time:java.util.Date,msg:String){println(time+msg)}32 log: (time: java.util.Date, msg: String)Unit33 34 scala> val log2 = log(new java.util.Date,_:String)35 log2: String => Unit = <function1>36 37 scala> log2("test1")38 Mon Sep 09 23:46:15 CST 2013test139 40 scala> log2("test2")41 Mon Sep 09 23:46:19 CST 2013test242 43 scala> log2("test3")44 Mon Sep 09 23:46:22 CST 2013test3


  6.闭包

 1 在java中匿名内部类访问局部变量是,局部变量必须声明为final(类似闭包的实现) 2  3 scala中没有那么麻烦: 4  5 scala> val more = 1 6 more: Int = 1 7  8 scala> val addMore = (x: Int) => x + more 9 addMore: Int => Int = <function1>10 11 scala> addMore(10)12 res19: Int = 11

(以上案例部分参考互联网已公开的案例和<Programming in Scala>中部分说明)

2、scala简单的并发编程模型

  scala的并发编程采用的是actor模型,即参与者模型(国内有个通俗术语叫做观察者模式)。

  简而言之就是每个参与者将自身的状态变化通过某种方式广播出去,其他参与者获取到这种状态变化后,再决定是否继续参与。

  scala使用精炼的函数式编程实现了actor模型,从而可以实现同一JVM单核并发,同一JVM多核并发,多个JVM之间并发,并且还可以实现某种意义上的IPC。

  典型的actor编程模型如下:

  

 1 Scala写法1: 2  3 import actors.Actor,actors.Actor._ 4  5 class A1 extends Actor { 6  7 def act {  8     react {  9         case n:Int=>println(perfect(n)) 10         }11     }12 }13 14 n to n+10 foreach (i=>{ 15     (new A1).start ! i16     }17 )
1 val aa = Array.fill(11)(actor { 2     react { 3         case n:Int=>println(perfect(n)) 4         }5     }6 )7 8 n to n+10 foreach (i=>aa(i-n) ! i)

两种写法只是区别在声明类方式上面,一种需要显式调用start,另外一个不需要而已。

不同JVM之间的通讯模型如下:

 1 服务器端: 2  3 object ActorServer extends Application { 4  5     import actors.Actor, actors.Actor._, actors.remote.RemoteActor 6  7     Actor.actor { // 创建并启动一个 actor 8  9       // 当前 actor 监听的端口: 300010 11       RemoteActor.alive(3000)12 13  14 15       // 在 3000 端口注册本 actor,取名为 server1。16 17       // 第一个参数为 actor 的标识,它以单引号开头,是 Scala 中的 Symbol 量,18 19       // Symbol 量和字符串相似,但 Symbol 相等是基于字符串比较的。20 21       // self 指代当前 actor (注意此处不能用 this)22 23       RemoteActor.register(‘server1, Actor.self)24 25  26 27       // 收到消息后的响应28 29       loop {30 31         Actor.react {case msg =>32 33           println("server1 get: " + msg)34 35         }36 37       }38 39     }40 41 }42 43  44 45 客户端:46 47   48 49 object ActorClient extends Application { 50 51     import actors.Actor, actors.remote.Node, actors.remote.RemoteActor 52 53     Actor.actor { 54 55       // 取得一个节点(ip:port 唯一标识一个节点) 56 57       // Node 是个 case class,所以不需要 new 58 59       val node = Node("127.0.0.1", 3000) 60 61  62 63       // 取得节点对应的 actor 代理对象 64 65       val remoteActor = RemoteActor.select(node, ‘server1) 66 67  68 69       // 现在 remoteActor 就和普通的 actor 一样,可以向它发送消息了! 70 71       println("-- begin to send message")72 73       remoteActor ! "ActorClient的消息" 74 75       println("-- end")76 77     } 78 79 }

scala其他的特点,比如:强类型,扩展性这里就不一一描述了。

上述的两点,应该属于scala与java之间最根本的特征了。

  

scala与java之间的那些事