Scala的程序被编译成Java字节码(生成class文件),所以可以运行在JVM上,并且可以调用Java的类库,兼容Java程序。

Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成OOP和函数式编程(FP)的各种特性:

  1. 面向对象特性:Scala是一种纯面向对象的语言,每个值都是对象。类名:采用PascalCase命名(如class MyFirstScalaClass)。方法名:采用camleCase命名(如def myMethodName())。与Java类似,变量命名也采用camelCase方式。Scala类扩展有两种途径:一种途径是子类继承(单继承),另一种途径是灵活的混入机制。这两种途径能避免多重继承的种种问题。
  2. 函数式编程:即函数也能当成值来使用。可以定义匿名函数、高阶函数、多层嵌套函数,并支持柯里化。Scala的case class、内置的模式匹配相当于FP的代数类型。利用Scala的模式匹配可以处理XML数据(这个过程类似于正则表达式)。
  3. 静态类型:即Scala具有的类型系统,编译时先检查类型,保证了代码的安全性、一致性。类型系统包含:泛型类、协变和逆变、标注、类型参数的上下限约束、把类别和抽象类型作为对象成员、复合类型、引用自己时显示指定类型、视图、多态方法。
  4. 扩展性:
  5. 并发性:使用Actor作为并发模型,但它不同于Thread,它相当于Thread的实体。在Scala中,多个Actor可以分别复用/使用同一个线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个,在2.10之后的版本中,使用Akka作为其默认Actor实现。Actor通过邮箱收发消息。——线程复用:线程的数量必须加以控制,因为盲目的大量创建线程反而会降低系统性能。于是不狂增数量,而是将已创建的线程进行重复使用,即线程使用完毕,不立即销毁,而是暂时放在连接池(其状态肯定是空闲了),以供下次可以继续使用这些已有的线程,而不必创建新的。

Scala比较流行的Web框架:Lift框架、Play框架。

1、脚本编程:运行一个HelloWorld的程序(保存到HelloWorld.scala文件中,文件名应与类名相同,否则无法编译):

object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}

在终端中,运行:scala HelloWorld.scala,即可输出。

2、Scala也可以交互式编程(进入终端):

当要使用的标识符(方法名等)与关键字冲突之时,要使用这个标识符就需要写在一对倒引号`之间,如线程的yield方法:Thread.`yield`()。

定义Scala的包:

1、第一种方法类似于Java,在一个文件开头定义包名,则该文件后面的所有代码都属于这个包:

package com.qunyh;
class HelloWorld() {
}

2、第二种方法类似于C#,指明包的作用域,于是一个文件中可以定义多个包:

package com.qunyh {
class HelloQunyh {
}
}

引用包(可以引用Java的包):

import java.awt.Color    //只引入Color类
import java.awt._ //引入包内所有成员

多行字符串:

val foo = """菜鸟教程
www.runoob.com
www.w3cschool.cc
www.runnoob.com
以上三个地址都能访问"""; //这是一个字符串,只不过是分多行:在一对"""之间

变量的声明:

一般变量用var声明,常量用val声明(这种声明的常量值以后就不能修改了,不然编译会报错)。

//可以指明变量类型(这种声明的时候可以不用初始化): 注意类型的位置
var myVar : String = "Foo";
val myVal : String = "Foo";
//也可以不指明(此时必须初始化,才能类型推断)
var yourVar = "Foo";
val yourVal = "Foo";
//多个变量一起声明
var xmax, ymax = 100; //两个变量值都为100

声明一个元组:

访问修饰符:

基本和Java一样,如果没有指定,默认访问级别是public。但是Scala的限定比Java更严格。

for循环:

1、第一种结构是for( var x <- Range ):其中Range区间可以是i to j或者i until j;而左箭头<-用于为变量x赋值。

object HelloWorld {
def main(args: Array[String]): Unit = {
var x = 0;
//for(x <- 1 to 10)
for(x <- 1 until 10) {
println("hello");
}
}
}
object Test {
def main(args: Array[String]) {
var a = 0;
var b = 0;
// 相当于二重循环:
//for(int a = 1; a <= 3; a++)
// for(int b = 1; b <= 3; b++)
for( a <- 1 to 3; b <- 1 to 3){
println( "Value of a: " + a );
println( "Value of b: " + b );
}
}
}

2、第二种结构for( var x <- List ):其中 List 变量是一个集合,for 循环会迭代所有集合的元素:

object Test {
def main(args: Array[String]) {
var a = 0;
var numList = List(1, 2, 3, 4);
for(a <- numList) {
println(a + "");
}
}
}

与其他的动态语言类似,Scala也有过滤器:

object Test {
def main(args: Array[String]) {
var a = 0;
var numList = List(1,2,3,4,5,6,7,8,9,10);
for(a <- numList
if a % 2 == 0; if a < 5) {
println(a + "");
}
}
}

而且还可以把List中过滤后剩下的,作为新的List返回(只是这种for循环的写法有点不同):

object Test {
def main(args: Array[String]) {
var a = 0;
var numList = List(1,2,3,4,5,6,7,8,9,10);
var retList = for{ a <- numList
if a % 2 == 0; if a < 5 } yield a; //这种for循环就不带循环体了
for(a <- retList) {
println(a + "");
}
}
}

Scala的循环控制语句没有break、continue等,但是提供了另一种语法来实现break语句的效果(需要导入control包)。

import scala.util.control._
object Test {
def main(args: Array[String]) {
var a = 0;
var control = new Breaks;
var numList = List(1,2,3,4,5,6,7,8,9,10);
//建议
control.breakable {
for(a <- numList) {
println(a + "");
if(a == 5) {
control.break;
}
}
}
for(a <- numList) {
println(a + "");
if(a == 5) {
control.break;
}
}
}
}

函数:

Scala 有函数和方法,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。我们可以在任何地方定义函数,甚至可以在函数内定义函数(内嵌函数),但是作用域就受到了限制。

Scala 函数声明格式如下:

def functionName ([参数列表]) : [return type];

如果不写等于号和方法主体(只有声明),那么方法会被隐式声明为"抽象(abstract)",包含它的类型(在类中)于是也是一个抽象类型。

函数定义格式如下(含body),其中返回值可以是任意的Scala数据类型:

def functionName ([参数列表]) : [return type] = {
function body
return [expr]
}

闭包:

Scala的闭包与C#的Lambda表达式类似,例如:

val multiplier = (i:Int) => i * factor;    //这就是一个闭包:箭头的左边是形参,右边是body(可能含返回值)。整个闭包可以当作一个函数,赋给一个变量

Scala的字符串:

String类型:

Scala本身没有String类,其类型实际上是Java String(java.lang.String),而Java的String对象的值是不可变的,如果修改字符串则意味着会产生一个新的字符串对象(暂时还没搞清楚,但我觉得是这个意思:修改之前=右边是一个字符串常量对象,变量只是引用其地址,而修改之后就是创建了一个新的字符串常量对象,变量只是更改其引用地址)。与Java、C#类似,要创建一个可修改的字符串,可以使用StringBuilder类。

StringBuilder类:

object Test {
def main(args: Array[String]) {
val buf = new StringBuilder;
buf += 'a';
buf ++= "bcdef"; //都不会重新创建对象
println( "buf is : " + buf.toString );
}
}

数组:

var z = Array("Runoob", "Baidu", "Google");
var z:Array[String] = new Array[String](3);
//多维数组
var myMatrix = ofDim[Int](3,3);
//合并数组
var myList1 = Array(1, 2, 3);
var myList2 = Array(4, 5, 6);
var myList3 = concat( myList1, myList2); //123456;concat函数:import Array._;
//创建区间数组:使用range方法,返回一个数组Array
var yourList1 = range(10, 20, 2); //arg3是步长,默认为1(不包含20)

集合:

Scala提供了一些集合类型的抽象,分为可变集合、不可变集合。

  • 可变集合可以在适当的时候更新或扩展,即添加、移除、修改一个集合元素。
  • 不可变集合一旦创建,其本身永远不会改变。但是仍然可以"模拟"可变集合的操作,这些操作还是不会改变不可变集合本身,却可以返回一个新的集合(新集合是否可变)。
// 常见的集合:
// 定义整型 List
val x = List(1,2,3,4)
// 定义 Set
var x = Set(1,3,5,7)
// 定义 Map
val x = Map("one" -> 1, "two" -> 2, "three" -> 3)
// 创建一个元组(这里包含两个不同类型元素)
val x = (10, "Runoob")
// 定义 Option
val x: Option[Int] = Some(5)

迭代器Iterator:

Iterator不是集合,而是一种访问集合的方法。迭代器的两个基本操作是next(返回集合中、迭代器的下一个元素,并更新迭代器自身的状态)和hasNext(判断集合中、迭代器的下一个元素是否存在)方法。可以先看代码,然后更容易理解:

object Test {
def main(args: Array[String]) {
val it = Iterator("Baidu", "Google", "Runoob", "Taobao");
while (it.hasNext){
println(it.next())
}
//还可以利用迭代器,很方便的查找max、min
var ita = Iterator(20,40,2,50,69, 90);
println("最小:" + ita.min);
//println("最小:" + ita.min);
//println("最大:" + ita.max); //一个迭代器,max、min只能用一次(再用就不支持操作),就算是用两次min也不行
//我的理解是:迭代器是迭代地找max、min,找到即遍历完整个"集合",就停止迭代了,
//再次使用就会抛出异常java.lang.UnsupportedOperationException //获取迭代器的长度size或length:即可以迭代的次数
//和min、max的用法相似:所以第一次是6,以后就是0了
var itb = Iterator(20,40,2,50,69, 90);
println(itb.size + ":" + itb.length);
//println(itb.size + ":" + itb.size);
}
}

Scala类与对象:

创建一个类和类的实例:

//Point类文件
class Point(val xc: Int, val yc: Int) {
var x: Int = xc;
var y: Int = yc; def move(dx: Int, dy: Int) {
x = x + dx;
y = y + dy;
println("x 的坐标为:" + x);
println("y 的坐标为:" + y);
}
}
//主函数
object Test {
def main(args: Array[String]) {
//创建一个Point对象
var pt = new Point(10, 20);
pt.move(10, 10);
}
}

Scala继承:

//继承刚才的Point类:Location类文件
class Location(override val xc: Int, override val yc: Int, val zc: Int) extends Point(xc, yc) {
var z: Int = zc; def move(dx: Int, dy: Int, dz: Int) {
x = x + dx;
y = y + dy;
z = z + dz;
println("x 的坐标为:" + x);
println("y 的坐标为:" + y);
println("z 的坐标为:" + z);
}
}
//主函数
object Test {
def main(args: Array[String]) {
//创建一个Point对象
var lc = new Location(10, 20, 10);
lc.move(10, 10, 10);
}
}

Scala Trait(特征):

特征相当于Java的接口,但是Scala的特征功能却更为强大。与接口不同,特征可以定义属性,还可以定义方法的实现,而Java接口却不能有实现(只能是抽象方法,而且接口不能包含成员变量,除了 static 和 final 变量)。因此在这个方面Trait更像Java的抽象类(可以有抽象方法与非抽象方法),但是抽象类只能是单继承,所以我觉得在Java中,接口就像是抽象类的精简版(只有定义,没有实现),而Scala Trait则像是结合了抽象类、接口,就像是一种可以多继承(接口)的抽象类。

Scala语言学习的更多相关文章

  1. Scala语言学习笔记——方法、函数及异常

    1.Scala 方法及函数区别 ① Scala 有方法与函数,二者在语义上的区别很小.Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量.换句话来说在类中定义的函数即是方法 ② Scal ...

  2. Scala语言学习笔记(3)

    类 // 定义并使用类 class User val user1 = new User // 主体构造器(primary constructor) class Point(var x: Int, va ...

  3. Scala语言学习笔记(2)

    表达式,值,变量,代码块,函数,方法 // 表达式 1 + 1 println(1 + 1) // 2 // 值(values)使用 val 关键字声明,带初值时类型可省略. val x = 1 + ...

  4. Spark Scala语言学习系列之完成HelloWorld程序(三种方式)

    三种方式完成HelloWorld程序 分别采用在REPL,命令行(scala脚本)和Eclipse下运行hello world. 一.Scala REPL. windows下安装好scala后,直接C ...

  5. Scala语言学习笔记(4)

    高阶函数 // 高阶函数 map val salaries = Seq(20000, 70000, 40000) val doubleSalary = (x: Int) => x * 2 val ...

  6. 关于学习Scala语言的一些感悟

    进入话题! 我们知道哈,Spark源码采用Scala语言编写,那么阅读Spark源码之前,是否一定先学Scala呢? 我个人认为,不必,只要我们有一些java或c++编写语言的基础,就可以看Spaar ...

  7. 【福利】送Scala语言入门视频学习资料

    没有套路真的是送!! 想要学好大数据,scala语言是必不可少的,spark和kafka等大数据重要组件都是用scala写的,想要彻底搞懂这些组件是如何运作的必须得看源码,而学习scala是看源码的必 ...

  8. 大数据spark学习第一周Scala语言基础

    Scala简单介绍 Scala(Scala Language的简称)语言是一种能够执行于JVM和.Net平台之上的通用编程语言.既可用于大规模应用程序开发,也可用于脚本编程,它由由Martin Ode ...

  9. 利用Scala语言开发Spark应用程序

    Spark内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情.如果你对Scala语言还不太熟悉,可 以阅读网络教程A Scala Tutorial for Ja ...

随机推荐

  1. python二叉树的深度遍历之先序遍历流程图

  2. 微信小程序制作家庭记账本之五

    第五天,开发进度没有进行,不知道该如何下手完成小程序的开发.

  3. VPS采用的几种常见技术(OVZ、Xen、KVM)介绍与对比

    很多人看到同样配置的VPS价格相差很大,甚是不理解,其实VPS使用的虚拟技术种类有很多,如OpenVZ.Xen.KVM.Xen和HVM与PV. 在+XEN中pv是半虚拟化,hvm是全虚拟化,pv只能用 ...

  4. Qt介绍1---QPA(Qt Platform Abstraction)

    Qt是一个夸平台的库(一直宣称“Qt everywhere”),但是Qt底层不是夸平台的.比如:Qt中Gui部件的核心类QWidget,该类除了qwidget.h 和 qwidget.cpp两个原文件 ...

  5. GoldenGate 12.3微服务架构与传统架构的区别

    随着Oracle GoldenGate 12c(12.3.0.1.0)的发布,引入了可用于复制业务数据的新架构. 多年来,这种架构有着不同的称谓,Oracle终于在最后GA发布的版本中,以“Micro ...

  6. 使用Holer外网SSH访问内网(局域网)Linux系统

    1. Holer工具简介 Holer exposes local servers behind NATs and firewalls to the public internet over secur ...

  7. Censor SCU - 4438

    frog is now a editor to censor so-called sensitive words (敏感词). She has a long text (p). Her job is ...

  8. intelliJ IDEA之使用svn或git管理代码

    intelliJ IDEA之使用svn管理代码 1.VCS—>import into Version Control—>Share Project(Subversion) 2.点击+    ...

  9. linux 安装 ImageMagick 和 imagick 扩展

    使用命令安装 1.依次运行以下命令 yum install ImageMagick yum install ImageMagick-devel yum install php-pear 安装php-p ...

  10. 一、数据库表中字段的增删改查,二、路由基础.三、有名无名分组.四、多app共存的路由分配.五、多app共存时模板冲突问题.六、创建app流程.七、路由分发.八、路由别名,九、名称空间.十、反向解析.十一、2.x新特性.十二、自定义转换器

    一.数据库表中字段的增删改查 ''' 直接在modules中对字段进行增删改查 然后在tools下点击Run manage.py Task执行makemigrations和migrate 注意在执行字 ...