首页 技术 正文
技术 2022年11月15日
0 收藏 980 点赞 3,954 浏览 7574 个字

  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.可传递
  

 def  func(f:()  =>  String)  =  println(f())
func(() => "hi")
//output: hi def foo() = "ok"
func(foo)
//output: ok val fun = (x:Int) => print(x)
fun(2)
//output:2

  2.嵌套函数

 def foo(){
def bar(){
println("hi")
}
bar //exec
} foo //output:hi

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

 def fun1(){
.....
this
} def fun2(){
....
this
} //两个函数可以如下方式使用
fun1().fun2()

  3.匿名函数

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

  4.高阶函数

 第一种:用函数做参数的函数。eg: def f2(f:() => Unit) {f()} def f1(){println(1)} f2(f1) f2(() => println("hi")) //传入匿名函数 第二种:产生的结果是一个函数的函数。eg: def hf():Int => Int = x => x +1 val fun = hf fun(2) //output:3

  5.函数柯里化

 当函数具有多个参数时
def sum(x:Int,y:Int) = x + y //参数被打散后,两个参数分开
def sum2(x:Int)(y:Int) = x + y sum2(1)(2) //output:3 scala> def first(x:Int)=(y:Int) => x+y
first: (x: Int)Int => Int scala> first(1)
res10: Int => Int = <function1> scala> val second=first(1)
second: Int => Int = <function1> scala> second(2)
res11: Int = 3 函数链
把一个带有多个参数的函数,转换为多个只有一个参数的函数来执行 f(1)(2)(3) 相当于 ((f(1))(2))(3) 带入参数 1执行 fa(1) 然后 带入参数2执行 fb(2) 接着带入参数3执行fc(3) 最后得到结果 柯里化的实际用途?
控制抽象,可改变代码的书写风格 foo(res,()=>println(res)) foo(res)(()=> println(res)) foo(res){()=> println(res)}
实现部分应用函数
scala> def log(time:java.util.Date,msg:String){println(time+msg)}
log: (time: java.util.Date, msg: String)Unit scala> val log2 = log(new java.util.Date,_:String)
log2: String => Unit = <function1> scala> log2("test1")
Mon Sep 09 23:46:15 CST 2013test1 scala> log2("test2")
Mon Sep 09 23:46:19 CST 2013test2 scala> log2("test3")
Mon Sep 09 23:46:22 CST 2013test3

  6.闭包

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

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

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

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

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

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

  典型的actor编程模型如下:

  

 Scala写法1: import actors.Actor,actors.Actor._ class A1 extends Actor { def act {
react {
case n:Int=>println(perfect(n))
}
}
} n to n+10 foreach (i=>{
(new A1).start ! i
}
)
 val aa = Array.fill(11)(actor {
react {
case n:Int=>println(perfect(n))
}
}
) n to n+10 foreach (i=>aa(i-n) ! i)

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

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

  服务端:

  

 import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import org.andy.scala.actor.model.ActorDeal class ActorServer extends Actor { def act(){ alive(9999) //绑定端口
register('ActorServer, self) //注册服务类 while(true){
receive {
case str:String =>print("There is say "+str)
case _=>println("There is no message ")
}
} }
}

  客户端:

 import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import scala.actors.Actor
import org.andy.scala.actor.model.ActorDeal class ActorClient extends Actor {
def act(){
val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)
//每隔5秒发送一次
while(true){
actServer ! "Hello "
print("===Send Hello== ")
Thread.sleep(5000)
}
}
}

  其中后的效果如下:

客户端
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 success
There is say Hello
There is say Hello
There is say Hello
There is say Hello
There is say Hello

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

  对象定义如下:

 class ActorDeal extends Serializable {   var msg: String = ""   def dealPrint() = {
println("From deal " + msg)
}
}

  客户端:

 import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import scala.actors.Actor
import org.andy.scala.actor.model.ActorDeal class 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== ")
actServer!ad
println("===Send ad==")
Thread.sleep(5000)
}
}
}

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

  服务端:

 import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import org.andy.scala.actor.model.ActorDeal class 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 }
}

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

  好,运行后的结果如下:

 server init success
There is say Hello Receive AD
From deal WORLD
There is say Hello Receive AD
From deal WORLD
There is say Hello Receive AD
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.Actor
import 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.Actor
import 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之间最根本的特征了。

  

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,557
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,406
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898