1. Scala demo
Scala 环境配置参考:Scala 初识+环境搭建
Scala 的执行模式:
- 交互模式
- 脚本模式
1.1 交互模式
在 CMD 中,通过 scala 目录进入 scala 环境:
1.2 脚本模式
scala 的源文件以 .scala
结尾,编写一个源文件 Hello.scala
,并在命令行中执行:
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World!")
}
}
2. Scala 基础
2.1 数据类型
Scala 具有与 Java 相同的数据类型,并且具有相同的内存占用和精度。
数据类型 | 描述 |
---|---|
Byte | 8位有符号补码整数。数值区间为 -128 到 127 |
Short | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 |
Float | 32 位, IEEE 754 标准的单精度浮点数 |
Double | 64 位 IEEE 754 标准的双精度浮点数 |
Char | 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF |
String | 字符序列 |
Boolean | true或false |
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null 或空引用 |
Nothing | Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。 |
Any | Any是所有其他类的超类 |
AnyRef | AnyRef类是Scala里所有引用类(reference class)的基类 |
2.2 常量
常量: 通过 val 关键字定义常量,常量不能被重新赋值,常量的类型可以被推断,也可以显式的声明类型。
语法格式:val 变量名 [: 类型] = 变量值
1、 当常量用于表达式结果命名时,执行表达式后再引用该常量,不会再次计算
为表达式结果命名:
// 定义常量
scala> val x = 1 + 1
x: Int = 2 // 2
scala> x = 3
error: reassignment to val // 编译失败,不能重新赋值
2、 声明类型
// 自动推断类型
scala> val x = 1 + 1
x: Int = 2
// 显示声明类型
scala> val x: Int = 1 + 1
x: Int = 2
⚠️ Scala中建议默认使用val修饰,变量,除非有需要重新赋值的场景否则 val 更为安全。
2.3 变量
变量: 通过 var 关键字定义变量,变量可以被重新赋值,变量的类型可以被推断,也可以显式声明类型。
语法格式:var 变量名 [: 类型] = 变量值
// 定义变量
scala> var y = 1 + 1
y: Int = 2
// 重新赋值
scala> y = 3
y: Int = 3
// 显示声明类型
scala> val x: Int = 1 + 1
x: Int = 2
⚠️
2.4 表达式
表达式(Expression): 可计算的语句,scala中每一行语句就是一个表达式,scala中表达式末尾不需要写 ;
scala> 1 + 1
res0: Int = 2
scala> "Hello " + "World! "
res1: String = "Hello World! "
🌈 res0
、res1
是表达式自动创建的变量名称,用于指代表达式的计算结果。
⚠️ 如果将两行表达式写到同一行,则必须写 ;
2.5 代码块
代码块(Blocks): 将几条表达式组合起来,并用 { }
包装为一个整体,可称为代码块。
代码块的结果: 代码块中最后一个表达式的结果
println({
val x = 1 + 1
x + 1
})
// 输出: 3
val res = {
var i = 3
println(i)
}
println(res); // 输出: 3 ()
🌈 println
是个方法,其返回值为 Unit
类型,所以返回值为 ()
。
val res = {
var i = 3
println(i)
"abc"
123
4.5
}
println(res); // 输出: 3 4.5
2.6 方法
方法(Method): 方法由def关键字定义,def后面跟着一个方法名、参数列表、返回类型和方法体。
在面向对象的编程语言中,方法声明在类内,用来表示一些列对象的行为。
Scala 方法与 Java 方法的区别:
语言 | 方法 |
---|---|
Java | 返回值类型 方法名 (参数类型 参数名) {方法体} void main (String[] args) {} |
Scala | 方法名 (参数名: 参数类型 ) : 返回值类型 = {方法体} def main (args: Array[String]): Unit = {} |
实例:
def sum (a: Int, b: Int): Int ={
a + b
}
val res = sum(1, 2)
println(res) // 输出: 3
2.6.1 方法的参数
方法的参数设置默认值:
// 传递第二个参数
def sum (a: Int, b: Int = 2): Int ={
a + b
}
val res = sum(1, 3)
println(res) // 输出: 4
// 不传递第二个参数
def sum (a: Int, b: Int = 2): Int ={
a + b
}
val res = sum(1)
println(res) // 输出: 3
带名传参:
def sum (a: Int, b: Int = 2): Int ={
a + b
}
val res = sum(a = 3, b = 4)
println(res) // 输出: 7
**可变长度参数: **Scala中与Java类似的也提供了可变长度参数,每个方法只能包含一个可变长度参数,可变长度参数需要声明在参数列表末尾。
def sum2(num: Int*): Int = {
num.sum
}
val res2 = sum2(1,2,3)
println(res2) // 输出: 6
⚠️ sum
方法:def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
2.6.2 方法的返回值
Unit: Scala 中如果方法的参数列表与方法体之间不写 =
,则默认使用 :Unit
补全,Unit是用来弥补Java之类的编程语言中void无法用面向对象解释的缺陷。
Unit是一个类 这个类只有一个实例 ()
, 用来表示不需要返回值的方法的返回值类型。
def sum3(a: Int, b: Int){
a + b
}
val res3 = sum3(1, 2)
println(res3) // 输出: ()
需要返回值: 如果方法需要返回值 可以加上 =
,Scala会根据方法体的最后一行表达式的值 推断返回值类型。
def sum4(a: Int, b: Int) = {
a + b
"aaa"
1.4
}
val res4 = sum4(1, 2)
println(res4) // 输出: 1.4
return: Scala中如果希望方法体的最后一行作为返回值,省略return关键字不写,如果使用return关键字 必须明确声明返回值类型。
def sum5(a: Int, b: Int): Int = {
return a + b
}
val res5 = sum5(1, 2)
println(res5) // 输出: 3
2.7 函数
函数(Function): 带有参数的表达式,默认使用 def 声明。
语法格式:
def 函数名(函数参数:参数类型):返回值类型={
函数体
}
函数和方法的区别:
- 方法method 声明在类中(直接属于类),用来描述对象的行为
- 函数function 可以声明在任何位置,函数就是参数和返回值的映射关系
实例:
object Scala_Funciton {
// 方法,直接属于对象
def m1: Unit ={
// 函数
def m2: Unit ={
// 函数
def m3: Unit ={
}
}
}
}
2.7.1 声明函数
当函数体只有一行时,可以写在一行,并省略 {}
,能够自动化推断返回值类型。
def main(args: Array[String]): Unit = {
def add(a: Int) = a + 1
}
2.7.2 匿名函数
// 是一个 Int=>Int 类型的函数
(a: Int) => a + 1
// 输入参数类型 输出参数类型
Int => Int
// 变量名 变量类型 对应类型的实例
val f1: Int => Int = (a: Int) => a + 1 // 函数类型
val i: Int = 123
val s: String = "abc"
2.7.3 高阶函数
函数可以作为其他函数的参数
/**
* @param op 函数类型
* @return Int 类型
*/
def calc(i: Int, j: Int, op: (Int, Int) => Int) = {
op(i, j)
}
// 函数调用
// 第三个参数,传递一个函数
val calc_res = calc(1, 2, (a: Int, b: Int) => a + b)
println(calc_res) // 返回: 3
1、匿名函数 f 作为其他函数的参数时 f 的参数类型可以省略
val calc_res2 = calc(1, 2, (a, b) => a + b)
println(calc_res2) // 返回: 3
2、二元匿名函数f 作为其他函数的参数时,如果f的参数声明循序和调用顺序一致 并且f的每个参数都只使用了一次,可以用 _
代替
val calc_res3 = calc(1, 2, _+_)
println(calc_res3) // 返回: 3
函数可以作为其他函数的返回值
2.8 类
类: Scala中可以使用class关键字声明类,class仅仅是对象的模板,对象的抽象,类不能直接调用属性和方法。
案例:
object Scala_Class {
def main(args: Array[String]): Unit = {
// 可以使用new关键字 调用类的构造器 用于创建类的实例
val student = new Student()
// 对象可以调用自己的属性和方法
student.name
student.age
}
}
class Student() {
val name: String = "JOEL"
var age: Int = 123
}
构造器: Scala中类的声明就是主构造器,主构造器的参数如果使用 val 或者 var 修饰,直接作为类的成员属性。
object Scala_Class {
def main(args: Array[String]): Unit = {
val student = new Student("JOEL", 123)
student.name
student.age
}
}
class Student(val name: String, var age: Int) {
}
辅助构造器: Scala还允许给类添加辅助构造器,辅助构造器是一些使用 def 声明的方法,方法名叫 this, 辅助构造器需要直接或者间接的调用主构造器。
object Scala_Class {
def main(args: Array[String]): Unit = {
// 主构造器
val student1 = new Student("JOEL", 123)
// 一个参数的构造器
val student2 = new Student("JOEL")
// 无参构造器
val student3 = new Student()
}
}
// 相当于主构造器
class Student(val name: String, var age: Int) {
// 一个参数的构造器
def this(name: String) {
this(name, 123)
}
// 空参构造器
def this(){
this("未知")
}
}
2.9 对象
对象(Object):scala中添加了object关键字用于创建单例对象。
2.9.1 伴生
伴生: 如果在同一个Scala源代码文件中,出现名称完全相同的class和object,此时 类和对象互为伴生关系
- 类叫做对象的伴生类
- 对象叫做类的伴生对象
伴生对象和伴生类可以互相访问私有成员
由于object 中的成员可以直接被对象名调用,所以通常将类中类似 Java static 修饰的成员(公用的)封装在类的伴生对象中,而 class 中仅仅声明每个对象个性化的成员
// 类
class Persion {
// 声明类的属性时,可以使用 _ 代表对应类型的默认值
var name: String = _ // 默认为 Null
var age: Int = _ // 默认为 0
}
// 对象
object Persion{
def m1: Unit ={
println("Persion类的方法")
}
}
2.9.2 对象
对象: scala中添加了object关键字用于创建单例对象
案例:
object Scala_Object {
def main(args: Array[String]): Unit = {
Gamer.playLOL()
val person = new Person
person.name
person.age
}
}
object Gamer {
def playGame(): Unit = {
println("打的贼菜")
}
}
Java 调用 Scala 定义的对象
public class Test {
public static void main(String[] args) {
Person person = new Person();
// 相当于 get()
String name = person.name();
int age = person.age();
//相当于 set()
person.name_$eq("JOEL");
person.age_$eq(123);
}
}
如果在 Scala 中定义的对象,可以通过添加注解的方式,来显示的调用 get、set 方法。
import scala.beans.BeanProperty
class Person {
@BeanProperty
var name: String = _
@BeanProperty
var age: Int = _
}