Scala语法
一、Scala的数据类型
由于scala可以在Java环境中运行,所以他们的数据类型相似。例如:
Byte、Char、Short、Int、Long、Float、Double、Boolean
在Scala中各数据类型的关系如下
与Java的基本数据类型的包装类型相同,但是scala没有基本数据类型与包装类型的概念,统一都是类。scala自己会负责基本数据类型和引用类型的转换操作类型的加强版类型:scala使用很多加强类给数据类型增加了上百种增强的功能或方法。
例如,Scala还提供了RichInt、RichDouble、RichChar等类型,RichInt就提供了to方法,1.to(10),此处Int先隐式转换为RichInt,然后再调用其to方法。
Any是abstract类,它是Scala类继承结构中最底层的。所有运行环境中的Scala类都是直接或间接继承自Any这个类。
AnyVal:所有值类型的基类。
Nothing:所有类的子类,是一个类。Nothing没有对象,但是可以用来定义类型。
在cmd中运行的Scala结果
Null:所有AnyRef的子类,null是Null的唯一对象。
二、变量的定义
对比说明,在Java中,数据类型前有单独且必须的定义,这种属于强类型语言,例如
int num=10;
char ch=”a”;
Double num2=11.11;
而在Scala和JavaScript中就不需要这种强制定义,取而代之的是var和val,例如
var x=111;
var y=11.11;
var z=”hello”;val f=58;
在这里面,var定义变量;val定义常量
object VariableTest {def main(args: Array[String]) {//使用val定义的变量值是不可变的,相当于java里用final修饰的变量val i = 1//使用var定义的变量是可变的,在Scala中鼓励使用valvar s = "hello"//Scala编译器会自动推断变量的类型,必要的时候可以指定类型//变量名在前,类型在后val str: String = "world"println("i = " + i)println("s = " + s)println("str = " + str)}
}
运行结果为
i = 1
s = hello
str = worldProcess finished with exit code 0
三、基本操作符
scala的算术操作符与java的算术操作符也没什么区别,比如+、-、*、/、%等,以及&、|、^、>>、<<等。
但是,在scala中,这些操作符是数据类型的方法,比如1 + 1,可以写做1.+(1)
例如,1.to(10),又可以写做1 to 10
scala中没有提供++、--操作符,我们只能使用+和-,比如num = 1,num ++是错误的,必须写做num += 1。
四、字符串的插值操作
Scala中的三个字符串插值器:s、f、raw
s | 在任何字符串前加上s,就可以直接在串中使用变量了 |
f | 除了 s 的功能外(不指定格式就和 s 一样),还能进行格式化输出,在变量后用 % 指定输出格式 |
raw | 除了对字面值中的字符不做编码外,raw 插值器与 s 插值器在功能上是相同的 |
举栗:
1、输出“tom”的数据类型
2、引用“tom”并输出之后的数据类型
3、定义“tom”,“jim”并引用输出
五、条件表达式
- if
- if else(单分支)
- if else if else(多分支)
def main(args: Array[String]): Unit = {val x = 1//判断x的值,将结果赋给yval y = if (x > 0) 1 else -1//打印y的值println("y=" + y)//支持混合类型表达式val z = if (x > 1) 1 else "error"//打印z的值println("z=" + z)//如果缺失else,相当于if (x > 2) 1 else ()val m = if (x > 2) 1println("m=" + m)//在scala中每个表达式都有值,scala中有个Unit类,写做(),相当于Java中的voidval n = if (x > 2) 1 else ()println("n=" + n)
}
当y的值类型既可能为Int又可能为String时,它的类型被定义为Any,是Int和String的父类。
没有else时,会默认为else(),y的类型被定义为AnyVal
六、类型的转换
跟Java那些编程语言相同,Scala用的也是那一套
上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。
但是,Scala还是跟Java有点去别的
- scala中所有的类型都使用大写字母开头
- 整形使用 Int 而不是Integer
- scala中定义变量可以不写类型,让scala编译器自动推断
- Scala中默认的整型是Int, 默认的浮点型是: Double
scala中的类型转换分为值类型转换和引用类型转换 , 值类型转换分为:
- 自动类型转换
- 强制类型转换
自动类型转换
范围小的数据类型值会自动转换为范围大的数据类型值, 这个动作就叫: 自动类型转换.
自动类型转换从小到大分别为:
Byte, Short, Char -> Int -> Long -> Float -> Double
强制类型转换
范围大的数据类型值通过一定的格式(强制转换函数)可以将其转换成范围小的数据类型值, 这个动作就叫: 强制类型转换。
但是,使用强制类型转换的时候可能会造成精度缺失问题
var name = 1
1.name.toDouble
使用toDouble、toInt等方法,对象名.to方法可以实现简单的数据类型转换。
2.name.doubleValue
可以使用doubleValue、longValue、intValue三种方法,用于简单的数据类型转换。
3.Integer.valueOf(name)
可将整型或者字符串型转换为Integer型。
4.String.valueOf(name)
可将任一类型数据转换为字符串类型(包括字符数组)
更为复杂具体的转换,需自定义转换类型及方法,使用占位符对数据集中所有元素进行指定的方式转换。
七、块表达式
先扔个栗子:
object demo01 {def main(args: Array[String]): Unit = {val x = 0val result = {if(x < 0)1else if(x >= 1)-1else"error"}println(result)}
}
在Scala中,{ }包含一系列表达式,其结果也是一个表达式。块语句中最后一个表达式的值就是块的值。
这个对于那种需要多步初始化的val的值很有用,例如:
val price = { val a = 5-c; val b=c+5;val c=3;sqrt(a*b) }
{ }块的值其最后一个表达式(粗体),a和b只是中间的计算值,很干净的部分而言不可见了。
在Scala中,赋值动作是没有值的——或者,更严谨的说:他们的值是Unit类型的。Unit类型等同于java或c++中的void,而这种类型只有一个值,写做()。
一个以赋值语句结尾的块,比如:{r= r*n; n -=n} 返回的是Unit类型的,写函数的时候要注意这一点。
由于赋值语句是Unit类型的,所以不能穿接起来,例如:x = y = 1; y=1的值是Unit ,也就是(),你肯定不会想把它赋值给x(而在java和c++中这些做法是有意义的)
八、循环语句
1、for循环
顾名思义,这里不过多解释,只通过代码表达
1、输出1到10(Scala中“-”是“=”)
2、输出1到9(包含开头不包含结尾)
3、遍历字符串(相当于java中的fore)
4、通过下标遍历字符串(length)(charAt() 方法用于返回参数中传递的索引的字符。)
5、遍历数组
6、通过下标遍历数组
7、双重循环
栗子:输出个位数与十位数不相同的两位数(个位、十位数均从1-3取值)
8、数组操作
对数组中的每个数乘以10,生成一个新数组
另一个方法
for 循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。Scala 中 for 循环是有返回值的。如果被循环的是 Map,返回的就是Map,被循环的是 List,返回的就是 List,以此类推。
把数组中的偶数取出来乘以100得到一个新的数组
方法一(俩):
方法二(俩):
2、while循环
while循环:基本语义与Java相同。
3、do while循环
至少执行一次
九、操作符重载
在scala里面没有运算符,所有的符号其实都是方法。
栗子:
相当于是,1这个实例调用+方法,传入了一个参数2
定义一个 + 方法
十、方法的定义
定义一个m方法
可以不写返回值类型,会自动将方法体的最后一行作为返回值,并推导出其类型。但是递归方法一定要写返回值类型。
如果显示的指明了没有返回值,即使方法体的最后一行有返回值,也不会有值返回。
定义无参的方法(方法名 参数 返回值类型)
无返回值的三种定义方法:(第一种:正常,第二种:不写Unit,第三种:不写=)
如果方法中没有参数的话小括号是可以省略的,但是调用的时候,就不能加括号了
变长参数
在Scala中,有时我们需要将方法定义为参数个数可变的形式,则此时可以使用变长参数定义方法。
def sum(nums: Int*) = {
var res = 0
for (num <- nums)res += num
res
}
sum(1, 2, 3, 4, 5)
十一、柯里化
柯里化指的是将原来接收多个参数的方法,变成新的接收一个参数的方法。
之前用过的fold
不传使用默认值,传值使用传了的值,传三个参数列表的情况,注意,当传入一个参数时,返回的<function1>