scala与java之间的关系

来源:互联网 发布:电信网络改移动网络 编辑:程序博客网 时间:2024/05/21 04:41

FROM: http://www.cnblogs.com/vikings-blog/p/3942417.html 

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 import scala.actors._ 2 import scala.actors.Actor._ 3 import scala.actors.remote._ 4 import scala.actors.remote.RemoteActor._ 5 import org.andy.scala.actor.model.ActorDeal 6  7 class ActorServer extends Actor { 8    9     def act(){10       11       alive(9999) //绑定端口12       register('ActorServer, self) //注册服务类13       14       15       while(true){16         receive  {17           case str:String =>print("There is say "+str)18           case _=>println("There is no message ")19         }20       }21       22     }23 }
复制代码

  客户端:

复制代码
 1 import scala.actors._ 2 import scala.actors.Actor._ 3 import scala.actors.remote._ 4 import scala.actors.remote.RemoteActor._ 5 import scala.actors.Actor 6 import org.andy.scala.actor.model.ActorDeal 7  8 class ActorClient extends Actor { 9     def act(){10       val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)11           //每隔5秒发送一次   12       while(true){13         actServer ! "Hello "14         print("===Send Hello==  ")15         Thread.sleep(5000)16       }17     }18 }
复制代码

  其中后的效果如下:

复制代码
客户端client init success===Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad=====Send Hello==  ===Send ad==服务端server init successThere is say HelloThere is say HelloThere is say HelloThere is say HelloThere is say Hello
复制代码

  这个模型是最简单的不同JVM之间的通讯,我们再添加一点难度!传递一个对象尝试一下:

  对象定义如下:

复制代码
1 class ActorDeal extends Serializable {2 3   var msg: String = ""4 5   def dealPrint() = {6     println("From deal " + msg)7   }8 }
复制代码

 

  客户端:

复制代码
 1 import scala.actors._ 2 import scala.actors.Actor._ 3 import scala.actors.remote._ 4 import scala.actors.remote.RemoteActor._ 5 import scala.actors.Actor 6 import org.andy.scala.actor.model.ActorDeal 7  8 class ActorClient extends Actor { 9     def act(){10       val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)11       var ad = new ActorDeal()12       ad.msg ="WORLD"13       while(true){14         actServer ! "Hello "15         print("===Send Hello==  ")16         actServer!ad17         println("===Send ad==")18         Thread.sleep(5000)19       }20     }21 }
复制代码

  高亮部分为新增的对象操作

  服务端:

复制代码
 1 import scala.actors._ 2 import scala.actors.Actor._ 3 import scala.actors.remote._ 4 import scala.actors.remote.RemoteActor._ 5 import org.andy.scala.actor.model.ActorDeal 6  7 class ActorServer extends Actor { 8     RemoteActor.classLoader= getClass().getClassLoader() 9   10     def act(){11       12       alive(9999)13       register('ActorServer, self)14       15       16       while(true){17         receive  {18           case ad:ActorDeal => dealAD(ad)19           case str:String =>print("There is say "+str)20           case _=>println("There is no message ")21         }22       }23       24     }25     26     def dealAD(adm:ActorDeal)={27       println("Receive AD")28       adm.dealPrint29       30     }31 }
复制代码

 

  标红的语句是最重要的一句,如果没有这句,scala actor将会报ClassNotFound异常。所以一定要添加上去

  好,运行后的结果如下:

复制代码
1 server init success2 There is say Hello Receive AD3 From deal WORLD4 There is say Hello Receive AD5 From deal WORLD6 There is say Hello Receive AD7 From deal WORLD
复制代码

 

  既然写到分布式编程了,那么就再添加一点reply的东西。

  下面的代码表示的服务端如何给客户端回复响应,请看代码:

  服务端

  

复制代码
import scala.actors._import scala.actors.Actor._import scala.actors.remote._import scala.actors.remote.RemoteActor._import org.andy.scala.actor.model.ActorDealclass ActorServer extends Actor {    RemoteActor.classLoader= getClass().getClassLoader()      def act(){            alive(9999)      register('ActorServer, self)                  while(true){        receive  {          case ad:ActorDeal => dealAD(ad)          case str:String =>print("There is say "+str)          case _=>println("There is no message ")        }      }          }        def dealAD(adm:ActorDeal)={      println("Receive AD")      adm.dealPrint      reply("Yet I receive")    }}
复制代码

  高亮部分就服务端的回复语句。既然服务端有回复,那么客户端是不是也要关心一下呢?

  客户端

  

复制代码
import scala.actors._import scala.actors.Actor._import scala.actors.remote._import scala.actors.remote.RemoteActor._import scala.actors.Actorimport org.andy.scala.actor.model.ActorDealclass ActorClient extends Actor {    def act(){      val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)      var ad = new ActorDeal()      ad.msg ="WORLD"      while(true){        actServer ! "Hello "        print("===Send Hello==  ")        var fu =actServer!!ad        println("===Send ad==")        var result = fu()         println("===Receive=="+result)        Thread.sleep(5000)      }    }}
复制代码

  首先客户端调用“!!”就是一个等待响应的阻塞方法,这里只要收到服务端回复的确认字符串即可。

  结果如下:

  

client init success===Send Hello==  ===Send ad=====Receive==Yet I receive

   如果我们增加点难度,回复一个对象。那又该如何处理呢?请看代码:

  服务端:

复制代码
import scala.actors._import scala.actors.Actor._import scala.actors.remote._import scala.actors.remote.RemoteActor._import org.andy.scala.actor.model.ActorDealclass ActorServer extends Actor {    RemoteActor.classLoader= getClass().getClassLoader()      def act(){            alive(9999)      register('ActorServer, self)                  while(true){        receive  {          case ad:ActorDeal => dealAD(ad)          case str:String =>print("There is say "+str)          case _=>println("There is no message ")        }      }          }        def dealAD(adm:ActorDeal)={      println("Receive AD")      adm.dealPrint      adm.msg ="I have achieve target"      reply(adm)    }}
复制代码

  我们修改了对象数据,然后reply回去。

  这次客户端会有大动作,请看:

复制代码
import scala.actors._import scala.actors.Actor._import scala.actors.remote._import scala.actors.remote.RemoteActor._import scala.actors.Actorimport org.andy.scala.actor.model.ActorDealclass ActorClient extends Actor {    RemoteActor.classLoader = getClass().getClassLoader()    def act(){      val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)      var ad = new ActorDeal()      ad.msg ="WORLD"      while(true){        actServer ! "Hello "        print("===Send Hello==  ")        var fu =actServer!!ad        println("===Send ad==")        var result = fu()        **********************        Thread.sleep(5000)      }    }}
复制代码

  首先一定要重置classloader,否则又会报ClassNotFound。后面result就应该是接受回复的ActorDeal对象了,但fu()返回的是any对象,又如何转换为ActorDeal对象呢?

  请点击这里查看Scala如何类型强转 ,具体代码里面写的较为详细了。

  我们看看效果:

  

client init success===Send Hello==  ===Send ad==From deal I have achieve target

 

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

  

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