喵星之旅-调皮的大象-Scala语法基础

环境配置

概述

Scala将面向对象和函数式编程结合成一种简洁的高级语言。
语言特点如下:
(1)Scala和Java一样属于JVM语言,使用时都需要先编译为class字节码文件,并且Scala能够直接调用Java的类库。
(2)Scala支持两种编程范式面向对象和函数式编程。
(3)Scala语言更加简洁高效;语法能够化简,函数式编程的思想使代码结构简洁。
(4)作者马丁·奥德斯基设计Scala借鉴了Java的设计思想,同时优秀的设计也推动了Java语言的发展。

环境搭建

(1)首先确保JDK1.8安装成功
(2)下载对应的Scala安装文件scala-2.12.10.zip
(3)解压scala-2.12.10.zip,解压到任意没有中文的路径,例如D:\Tools
(4)配置Scala的环境变量 : SCALA_HOME 为安装路径;在path添加值%SCALA_HOME%\bin

在终端中输入scala可以使用相关语法。

idea中的hello world案例

创建一个项目。创建过程中选择scala语言会默认提示添加相关插件,提示需要重启。

重启后重新创建即可成功。
创建测试代码(我这里是默认生成的,和idea版本有关)

1
2
3
4
5
object Main {
def main(args: Array[String]): Unit = {
println("Hello world!")
}
}

如果是maven项目,先创建一个java的maven项目,然后右键项目添加scala支持即可(Add Framework Support)。

变量和数据类型

注释

Scala注释使用和Java完全一样。

变量和常量

常量:在程序执行的过程中,其值不会被改变的变量。

1
2
var 变量名 [: 变量类型] = 初始值		var i:Int = 10
val 常量名 [: 常量类型] = 初始值 val j:Int = 20

注意:能用常量的地方不用变量。

1
2
3
4
5
声明变量时,类型可以省略,编译器自动推导,即类型推导。
类型确定后,就不能修改,说明Scala是强数据类型语言。
变量声明时,必须要有初始值。
在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改。
var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.example

object Test01 {
def main(args: Array[String]): Unit = {
// 声明变量和常量
val a: Int = 10
var b: Int = 20


// 常量值无法修改
// a = 20
b = 30
// (1)声明变量时,类型可以省略,编译器自动推导,即类型推导
val c = 30

// (2)类型确定后,就不能修改,说明Scala是强数据类型语言。

// b = "30"

// (3)变量声明时,必须要有初始值
val d: Int = 0

// var d1:Int = _

val test02 = new Test02()
println(test02.i)

// (4)var修饰的对象引用可以改变,val修饰的对象则不可改变,
// 但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)
val person0 = new Person()
var person1 = new Person()

// 引用数据类型的常量和变量能否替换成别的对象
// var 可以修改引用数据类型的地址值 val不行
person1 = new Person()

// 引用数据类型中的属性值能否发生变化 取决于内部的属性在定义的时候是var还是val
// person0.name = "lisi"
person0.age = 11

}


}

class Test02 {

// scala中类的属性 如果是var变量也能使用默认值 但是必须要有等号
var i: Int = _
}

class Person {
val name: String = "zhangsan"
var age: Int = 10
}

标识符的命名规范

Scala对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可以起名字的地方都叫标识符。

1)命名规则
Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化(java可支持中文字母即汉字,但是scala显然不可以),有以下三种规则:
(1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)用反引号....包括的任意字符串,即使是Scala关键字(39个)也可以

注意:正常使用不能只遵守规则,必须按照规范来写,即使用大小驼峰命名法。

字符串输出

基本语法
(1)字符串,通过+号连接。
(2)重复字符串拼接。
(3)printf用法:字符串,通过%传值。
(4)字符串模板(插值字符串):通过$获取变量值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
object Test03 {
def main(args: Array[String]): Unit = {
// (1)字符串,通过+号连接
println("hello" + "world")

// (2)重复字符串拼接
println("linhailinhai" * 5)

// (3)printf用法:字符串,通过%传值。
printf("name: %s age: %d\n", "linhai", 8)

// (4)字符串模板(插值字符串):通过$获取变量值
val name = "linhai"
val age = 8

val s1 = s"name: $name,age:${age}"
println(s1)

val s2 = s"name: ${name + 1},age:${age + 2}"
println(s2)


// (5)长字符串 原始字符串
println("我" +
"是" +
"一首" +
"诗")

//多行字符串,在Scala中,利用三个双引号包围多行字符串就可以实现。
// 输入的内容,带有空格、\t之类,导致每一行的开始位置不能整洁对齐。
//应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为连接符,
// 在多行换行的行头前面加一个“|”符号即可。
println(
"""我
|是
|一首
|诗
|""".stripMargin)

println("""
|select id,
| age
|from user_info
|""".stripMargin)


println(s"""
|${name}
|${age}
|""".stripMargin)
}
}

数据类型

1
2
3
4
5
6
7
8
9
Any: 所有类的父类
AnyVal: 值类型
Byte、Short、Int、Float、Double、Long、Char、Boolean
Unit: 相当于java的void,有一个实例()
Stringops: 对java字符串扩展的统称
AnyRef: 引用类型
String、java数组\集合\class、scala数组\集合\class
Null: 是所有引用类型的子类,有一个实例null,null一般用于给引用类型赋予初始值,在赋予初始值的时候必须指定变量类型。
Nothing: 所有类型的子类

值类型

和java基本数据类型相似,只是这里是对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 整数类型
val i1 = 1

val l = 1L

val b1: Byte = 2
// val b0: Byte = 128



//编译器对于常量值的计算 能够直接使用结果进行编译
// 但是如果是变量值 编译器是不知道变量的值的 所以判断不能将大类型的值赋值给小的类型
val i2 = 1
// val b3: Byte = i2 + 1
// println(b3)

// Scala程序中变量常声明为Int型,除非不足以表示大数,才使用Long
val l1 = 2200000000L

// 浮点数介绍
// 默认使用double
val d: Double = 3.14

// 如果使用float 在末尾添加f
val fl = 3.14f

// 浮点数计算有误差
println(0.1 / 3.3)

// 字符常量是用单引号 ' ' 括起来的单个字符。
val c1: Char = 'a'
val c2: Char = 65535

// \t :一个制表位,实现对齐的功能
val c3: Char = '\t'

// \n :换行符
val c4: Char = '\n'
println(c3 + 0)
println(c4 + 0)

// \\ :表示\
val c5: Char = '\\'
println(c5 + 0)

// \" :表示"
val c6: Char = '\"'
println(c6 + 0)

val bo1: Boolean = true
val bo2: Boolean = false

Unit类型、Null类型和Nothing类型

Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null , Null 类型只有一个实例值null
Nothing Nothing类型在Scala的类层级最低端;它是任何其他类型的子类型。当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性)

Unit类型用来标识过程,也就是没有明确返回值的函数。
由此可见,Unit类似于Java里的void。Unit只有一个实例——( ),这个实例也没有实质意义。

1
2
3
4
5
6
7
8
9
10
11
12
// unit
val unit1: Unit = {
10
println("1")
}
println(unit1)

// 如果标记对象的类型是unit的话 后面有返回值也没法接收
// unit虽然是数值类型 但是可以接收引用数据类型 因为都是表示不接收返回值
val i3: Unit = "aa"
println(i3)

Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// scala当中使用的字符串就是java中的string
val aa: String = "aa"

// null
var aa1: String = "aa"

aa1 = "bb"
aa1 = null
if (aa1 != null) {
val strings: Array[String] = aa1.split(",")
}

// 值类型不能等于null,idea不会识别报错 编译器会报错
var i4 = 10
// i4 = null

Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。

类型转换

数值类型自动转换

与java规则一致。

自动提升原则:
有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。

强制类型转换

自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。

1
2
Java  :  int num = (int)2.5
Scala : var num : Int = 2.7.toInt
1
2
3
4
5
6
7
8
// 强制类型转换
val d1 = 2.999
// 将数据由高精度转换为低精度,就需要使用到强制转换
println((d1 + 0.5).toInt)


// 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
println((10 * 3.5 + 6 * 1.5).toInt)

数值类型和String类型间转换

基本类型转String类型(语法:将基本类型的值+”” 即可)。

String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//    基本类型转String类型(语法:将基本类型的值+"" 即可)
val string: String = 10.0.toString
println(string)

val str: String = 1 + ""

// String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)
val double: Double = "3.14".toDouble

println(double + 1)
println(double.toInt)

// 不能直接将小数类型的字符串转换为整数 需要先转换为double再转换int
// println("3.14".toInt)

// 标记为f的float数能够识别
println("12.6f".toFloat)

运算符

Scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。

1
2
Scala:==更加类似于Java中的equals
Scala中没有++、--操作符,可以通过+=、-=来实现同样的效果

在Scala中其实是没有运算符的,所有运算符都是方法。
当调用对象的方法时,点.可以省略
如果函数参数只有一个,或者没有参数,()可以省略

1
2
3
4
5
6
7
8
9
10
11
12
// 标准的加法运算
val i:Int = 1.+(1)

// (1)当调用对象的方法时,.可以省略
val j:Int = 1 + (1)

// (2)如果函数参数只有一个,或者没有参数,()可以省略
val k:Int = 1 + 1

println(1.toString())
println(1 toString())
println(1 toString)

流程控制

分支控制if-else

可以向java中使用一样

1
2
3
4
5
6
7
8
9
10
println("input age")
var age = StdIn.readInt()

if (age < 18){
println("童年")
}else if(age>=18 && age<60){
println("中年")
}else{
println("老年")
}

ifelse有返回值

Scala中if else表达式其实是有返回值的,具体返回值取决于满足条件的代码体的最后一行内容。

1
2
3
4
5
6
7
8
9
10
11
12
println("input age")
var age = StdIn.readInt()

val res :String = if (age < 18){
"童年"
}else if(age>=18 && age<60){
"中年"
}else{
"老年"
}

println(res)

Scala中返回值类型不一致,取它们共同的祖先类型

1
2
3
4
5
6
7
8
9
10
11
12
println("input age")
var age = StdIn.readInt()

val res:Any = if (age < 18){
"童年"
}else if(age>=18 && age<60){
"中年"
}else{
100
}

println(res)

Java中的三元运算符可以用if else实现.

1
2
3
4
5
println("input age")
var age = StdIn.readInt()
val res:Any = if (age < 18) "童年" else "成年"

println(res)

For循环控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// scala中的for循环基础语法
for (i <- 0 to 5) {
println(i)
}

for (i <- 0 until 5) {
println(i)
}

// for循环的本质
// to是整数的方法 返回结果是一个集合
// 使用变量i 循环遍历一遍 后面集合的内容
val inclusive: Range.Inclusive = 0.to(5)
println(inclusive.toList)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 循环守卫
for (i <- 0 to 10) {
if (i > 5) {
println(i)
}
}

for (i <- 0 to 10 if i > 5) {
println(i)
}

// 循环返回值
val ints = for (i <- 0 to 3) yield {
10
}
println(ints)

While和do..While循环控制

和java一致。

循环中断

采用Scala自带的函数,退出循环

1
2
3
4
5
6
7
8
Breaks.breakable(
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) Breaks.break()
}
)

println("正常结束循环")

对break进行省略

1
2
3
4
5
6
7
8
9
10
import scala.util.control.Breaks.{break, breakable}

breakable {
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) break
}
}

println("正常结束循环")

猜数字

文章目录
  1. 环境配置
    1. 概述
    2. 环境搭建
    3. idea中的hello world案例
  2. 变量和数据类型
    1. 注释
    2. 变量和常量
    3. 标识符的命名规范
    4. 字符串输出
    5. 数据类型
    6. 值类型
    7. Unit类型、Null类型和Nothing类型
    8. 类型转换
      1. 数值类型自动转换
      2. 强制类型转换
      3. 数值类型和String类型间转换
  3. 运算符
  4. 流程控制
    1. 分支控制if-else
      1. 可以向java中使用一样
      2. ifelse有返回值
    2. For循环控制
    3. While和do..While循环控制
    4. 循环中断
  5. 猜数字
|