Scala基本语法
scala的基本语法
注释
对于scala的注释,简而言之就是一句话,和java的注释一模一样
基本语法
(1)单行注释://
(2)多行注释:/* */
(3)文档注释:/**
*
*/
代码示例:
package com.doitedu.demo01
object TestNotes {
def main(args: Array[String]): Unit = {
//(1)单行注释://
println("涛哥")
//(2)多行注释:/* */
/*
println("涛哥")
println("行哥")
*/
//(3)文档注释:
/**
*
*/
/**
* println("乃哥")
* println("雨哥")
* println("行哥")
*/
}
}
变量和常量(重点)
// 回顾:Java 变量和常量语法
// 变量类型 变量名称 = 初始值
int a = 10
// final 常量类型 常量名称 = 初始值
final int b = 20
scala定义变量常量的基本语法
Scala
// var 变量名 [: 变量类型] = 初始值
var i:Int = 10 variable :可变的
// val 常量名 [: 常量类型] = 初始值
val j:Int = 20 value :值
var variable 可变的 代表声明变量
val value 值 代表声明常量
注意:
• val 在编程的过程中我们大部分的操作是获取值或者是获取一个创建好的对象,然后操作对象中的属性,很少改变这个对象变量
• val 是线程安全的 , 在使用的时候效率更高
• 优先使用val ,但是当变量后续的需要变化的时候使用var
package com.doitedu.demo02
object TestVar {
def main(args: Array[String]): Unit = {
//(1)声明变量时,类型可以省略,编译器自动推导,即类型推导
var age = 18
age = 30
//(2)类型确定后,就不能修改,说明 Scala 是强数据类型语言。
// age = "zhangsan" // 错误
//(3)变量声明时,必须要有初始值
// var name //错误
//(4)在声明/定义一个变量时,可以使用 var 或者 val 来修饰,var 修饰的变量可改变,val 修饰的变量不可改。
var num1 = 10 // 可变
val num2 = 20 // 不可变
num1 = 30 // 正确
//num2 = 100 //错误,因为 num2 是 val 修饰的
}
}
object demo03{
def main(args: Array[String]): Unit = {
// p1 是 var 修饰的,p1 的属性可以变,而且 p1 本身也可以变
var p1 = new Person()
p1.name = "zhangsan"
p1 = null
// p2 是 val 修饰的,那么 p2 本身就不可变(即 p2 的内存地址不能变),
但是,p2 的属性是可以变,因为属性并没有用 val 修饰。
val p2 = new Person()
p2.name="jinlian"
// p2 = null // 错误的,因为 p2 是 val 修饰的
}
}
class Person{
var name : String = "jinlian"
}
练一练:
多易现在开售了一个小课堂来卖课(小型的电商平台):
对于销售这块而言,我们是不是要存在一些属性字段:
店铺名称:多易教育
课程名称:java基础,mysql,hadoop.....
讲课老师:源哥,涛哥,星哥,行哥
课程的价格:199,299,399,99
红包类型: 首次购买红包,老学员红包
红包金额:9.9 18.8
活动名称:老用户再次购买,新用户首次购买,学员推荐购买
活动类型:6.18 10.24 11.11
活动折扣力度:9折 5折 8.8折
购买用户用户名:zhangsan,lisi
用户手机号:18860875775,18860875776
用户现在的职位:etl工程师,大数据开发工程师,数仓工程师
用户的邮箱:email
订单号:111122223333
订单金额:398
代码:
package com.doitedu
object demo01{
/**
* 店铺名称:多易教育
* 课程名称:java基础,mysql,hadoop.....
* 讲课老师:源哥,涛哥,星哥,行哥
* 课程的价格:199,299,399,99
* 红包类型: 首次购买红包,老学员红包
* 红包金额:9.9 18.8
* 活动名称:老用户再次购买,新用户首次购买,学员推荐购买
* 活动类型:6.18 10.24 11.11
* 活动折扣力度:9折 5折 8.8折
* 购买用户用户名:姜海涛,江一
* 用户手机号:18860875775,1886087,5776
* 用户现在的职位:etl工程师,大数据开发工程师,数仓工程师
* 用户的邮箱:email
* 订单号:111122223333
* 订单金额:119.4
*/
def main(args: Array[String]): Unit = {
//店铺名称:多易教育
val shopName = "多易教育"
//课程名称:java基础,mysql,hadoop.....
val subjectName = "java基础"
//讲课老师:源哥,涛哥,星哥,行哥
val tName = "涛哥"
//课程的价格:199,299,399,99
val subjectPrice = 199.00
//红包类型: 首次购买红包,老学员红包
val bonusType = "new"
//红包金额
val bonus = 9.9
//活动名称
val activeName = "老用户再次购买"
//活动类型:6.18 10.24 11.11
val activeType = "程序员节"
//活动折扣力度
val activeDiscount = 0.6
//购买用户用户名
val userName = "haiTao Jiang"
//用户手机号
val tel = "13372090488"
//用户邮箱
val email = "[email protected]"
//订单号
val orderId = "111122223333"
//订单金额
val orderAmount = 119.4
}
}
标识符的命名规范
Scala 对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可
以起名字的地方都叫标识符。
命名规则:
Scala 中的标识符声明,基本和 Java 是一致的,但是细节上会有所变化,总结后有三点:
- 以字母或者下划线开头,后接字母、数字、下划线 正常情况下:字母加下划线偶尔来个数字
- 以操作符开头,且只包含操作符(+ - / # !等)
- 用反引号
....
包括的任意字符串,即使是 Scala 关键字(39 个)也可以
• package, import, class, object, trait, extends, with, type, for
• private, protected, abstract, sealed, final, implicit, lazy, override
• try, catch, finally, throw
• if, else, match, case, do, while, for, return, yield
• def, val, var
• this, super
• new
• true, false, null
练一练:
需求:判断 hello、Hello12、1hello、h-b、x h、h_4、ab、Int、、+-/#!、+-/#!1、if、if
,这些名字是否合法。
object Test01 {
def main(args: Array[String]): Unit = {
// (1)以字母或者下划线开头,后接字母、数字、下划线
var hello: String = "" // ok
var Hello12: String = "" // ok
var 1hello: String = "" // error 数字不能开头
var h-b: String = "" // error 不能用-
var x h: String = "" // error 不能有空格
var h_4: String = "" // ok
var _ab: String = "" // ok
var Int: String = "" // ok 因为在 Scala 中 Int 是预定义的字符,不是关键字,但不推荐
var _: String = "hello" // ok 单独一个下划线不可以作为标识符,因为_被认为是一个方法println(_)
//(2)以操作符开头,且只包含操作符(+ - * / # !等)
var +*-/#! : String = "" // ok
var +*-/#!1 : String = "" // error 以操作符开头,必须都是操作符
//(3)用反引号`....`包括的任意字符串,即使是 Scala 关键字(39 个)也可以
var if : String = "" // error 不能用关键字
var `if` : String = "" // ok 用反引号`....`包括的任意字符串,包括关键字
}
}
字符串输出
基本语法:
- 字符串,通过+号连接
- printf 用法:字符串,通过%传值。
- 字符串模板(插值字符串):通过$获取变量值
代码测试:
package com.doitedu.demo04
object TestString{
def main(args: Array[String]): Unit = {
var name: String = "jinlian"
var age: Int = 18
//(1)字符串,通过+号连接
println(name + " " + age)
//可以用$来引用变量,大括号{}可以写也可以不写,如果不写,中间要用空格隔开
//最前面小写的s就是固定写法,写了他相当于就是一个模板字符串,咱们可以用$去引用变量了
println(s"${name}今年${age}岁了")
//(2)printf 用法字符串,通过%传值。 他是不换行的,如果需要换行,那么要用\r\n来写在末尾换行
printf("name=%s age=%d\r\n",name,age)
val price = 119.99
printf("这个商品的价格是%.2f",price)
//(3)字符串,通过$引用
//多行字符串,在 Scala中,利用三个双引号包围多行字符串就可以实现。
//输入的内容,带有空格、\t 之类,导致每一行的开始位置不能整洁对齐。
//应用 scala 的 stripMargin 方法,在 scala 中 stripMargin 默认
是“|”作为连接符,//在多行换行的行头前面加一个“|”符号即可。
val sql =
"""
|select
|name,
|count(1) as cnt
|from
|table_a
|where name = "zhangSan"
|and age = 18
|group by name;
|""".stripMargin
println(sql )
//如果需要对变量进行运算,那么可以加${}
val sql01 =
"""
|select
|name,
|count(1) as cnt
|from
|table_a
|where name = "$name"
|and age = ${age+2}
|group by name;
|""".stripMargin
println(sql01 )
val s2 = s"name=$name"
println(s2)
}
}
printf中格式化输出的模板
%d 十进制数字
%s 字符串
%c 字符
%e 指数浮点数
%f 浮点数
%i 整数(十进制)
%o 八进制
%u 无符号十进制
%x 十六进制
数据类型(重点)
Java基本类型:char、byte、short、int、long、float、double、boolean
Java引用类型:(对象类型)
Java基本类型的包装类:Character、Byte、Short、Integer、Long、Float、Double、Boolean
由于Java有基本类型,而且基本类型不是真正意义的对象,即使后面产生了基本类型的包装类,但是仍然存在基本数据类型,所以Java语言并不是真正意思的面向对象。
• scala中的数据类型和java中数据类型最大的区别就是scala中的数据类型都是对象 , 也就是scala中没有原生的数据类型!
• scala中的数据类型分成两类 AnyVal(值类型)和AnyRef(引用类型) , 两种对象都属于Any ,都是对象
val age:Int = 23
age是一个Int数值类型的变量 , 数值类型的变量也属于一个对象 , 所以age变量就是一个对象,也拥有很多方法
注意:Java中基本类型和引用类型没有共同的祖先。
- Any : 所有类型的父类 , 类似于java中的Object
- AnyVal: 数值类型(简单类型) ==-》 对应的是java中的基本数据类型
- AnyRef: 引用数据类型
- Null: 引用类型的子类,类似于java中的null ==》 写了一个类,将null这个值封装在了这个Null里面
- Unit:对应Java中的void,表示方法没有返回值 ,他的值:() ==》 因为针对这个对象,重写了toString 方法
- Nothing: 所类型的子类,主要用在一个函数没有明确返回值时使用,通常异常时使用,表示此处有错
数据类型详细表:
Unit 类型、Null 类型和 Nothing 类型
数据类型 | 描述 |
---|---|
Unit | 表示无值,和其他语言中 void 等同。用作不返回任何结果的方法的结果类型。Unit 只有一个实例值,写成()。 |
Null | null , Null 类型只有一个实例值 null |
Nothing | Nothing 类型在 Scala 的类层级最低端;它是任何其他类型的子类型。当一个函数,我们确定没有正常的返回值,可以用 Nothing 来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性) |
类型转换
当Scala 程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这
个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
说明:
- 自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
- 把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。toInt toDouble
- (byte,short)和 char 之间不会相互自动转换。
- byte,short,char 他们三者可以计算,在计算时首先转换为 int 类型。
测试案例:
object Test {
def main(args: Array[String]): Unit = {
//(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数值类型,然后再进行计算。
var n = 1 + 2.0
println(n) // n 就是 Double
//(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
var n2 : Double= 1.0
//var n3 : Int = n2 //错误,原因不能把高精度的数据直接赋值和低精度。
//(3)(byte,short)和 char 之间不会相互自动转换。
var n4 : Byte = 1
//var c1 : Char = n4 //错误
var n5:Int = n4
//(4)byte,short,char 他们三者可以计算,在计算时首先转换为 int类型。
var n6 : Byte = 1
var c2 : Char = 1
// var n : Short = n6 + c2 //当 n6 + c2 结果类型就是 int
// var n7 : Short = 10 + 90 //错误
}
}
运算符
算术运算符
测试代码:
object Test {
def main(args: Array[String]) {
var a = 10;
var b = 20;
var c = 25;
var d = 25;
println("a + b = " + (a + b) );
println("a - b = " + (a - b) );
println("a * b = " + (a * b) );
println("b / a = " + (b / a) );
println("b % a = " + (b % a) );
println("c % a = " + (c % a) );
}
}
关系运算符
代码测试:
def main(args: Array[String]) {
var a = 10;
var b = 20;
println("a == b = " + (a == b) );
println("a != b = " + (a != b) );
println("a > b = " + (a > b) );
println("a < b = " + (a < b) );
println("b >= a = " + (b >= a) );
println("b <= a = " + (b <= a) );
}
逻辑运算符
代码测试:
val a = true
val b = false
println("a && b = " + (a && b))//false
println("a || b = " + (a || b))//true
println("!(a && b) = " + !(a && b))//true
赋值运算符
注意:scala中是没有++ -- 替换 += -=
代码测试:
object Test {
def main(args: Array[String]): Unit = {
var r1 = 10
r1 += 1 // 没有++
r1 -= 2 // 没有--
}
}
位运算符
测试代码:
object TestPosition {
def main(args: Array[String]): Unit = {
// 测试:1000 << 1 =>10000
var n1 :Int =8
n1 = n1 << 1
println(n1) //16
}
}
优先级
流程控制
Scala中的流程控制和java基本一致
范围数据循环(To)
基本语法
for(i <- 1 to 10){
println(i)
}
(1)i 表示循环的变量,<- 规定 to
(2)i 将会从 1-3 循环,前后闭合
需求:输出 5 句 "hello world"
object TestFor {
def main(args: Array[String]): Unit = {
for(i <- 1 to 5){
println("hello world"+i)
}
}
}
范围数据循环(Until)
基本语法:
for(i <- 1 until 5) {
println(i)
}
(1)这种方式和前面的区别在于 i 是从 1 到 5-1 即[0,5)
(2)即使前闭合后开的范围
练习:
需求:用until输出 5 句 "hello world"
Scala
object TestFor {
def main(args: Array[String]): Unit = {
for(i <- 1 until 5+1){
println("hello world"+i)
}
}
}
循环守卫
基本语法
for(i <- 1 to 3 if i != 2) {
println(i)
}
// 循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环体内部,为 false 则跳过,类似于 continue。
// 代码等价:
for (i <- 1 to 3){
if (i != 2) {
print(i + " ")
}
}
// 需求:输出 1 到 5 中,不等于 3 的值
object TestFor {
def main(args: Array[String]): Unit = {
for (i <- 1 to 5 if i != 3) {
println(i + "doit")
}
}
}
循环步长
基本语法:
说明:by 表示步长
for (i <- 1 to 10 by 2) {
println("i=" + i)
}
// 需求:输出 1 到 10 以内的所有奇数
for (i <- 1 to 10 by 2) {
println("i=" + i)
}
结果:
i=1
i=3
i=5
i=7
i=9
引入变量:
基本语法:
for(i <- 1 to 3; j = 4 - i) {
println("i=" + i + " j=" + j)
}
说明:
(1)for 推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑
(2)for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下
举例:
for {
i <- 1 to 3
j = 4 - i
} {
println("i=" + i + " j=" + j)
}
// 等价得代码:
Scala
for (i <- 1 to 3) {
var j = 4 - i
println("i=" + i + " j=" + j)
}
循环返回值
基本语法:
val res = for(i <- 1 to 10) yield i
println(res)
// 说明:将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字。
// 练习:需求:将原数据中所有值乘以 2,并把数据返回到一个新的集合中。
object TestFor {
def main(args: Array[String]): Unit = {
var res = for(i <-1 to 10) yield {
i * 2
}
println(res)
}
}
输出结果:
Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
倒序打印
说明:如果想倒序打印一组数据,可以用 reverse。
需求:倒序打印 10 到 1
for(i <- 1 to 10 reverse){
println(i)
}
循环中断
基本说明:
Scala 内置控制结构特地去掉了 break 和 continue,是为了更好的适应函数式编程,推荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable控制结构来实现 break 和 continue 功能。
方式 1:采用异常的方式退出循环
object Demo_while {
def main(args: Array[String]): Unit = {
try {
for (emel <- 1 to 10) {
println(emel)
if (emel == 5) {
throw new RuntimeException
}
}
} catch {
case e: Exception =>
}
println("hello")
}
}
方式 2:采用 Scala 自带的函数,退出循环
import scala.util.control.Breaks
object Demo_while {
def main(args: Array[String]): Unit = {
Breaks.breakable(
for (emel <- 1 to 10) {
println(emel)
if (emel == 5) {
Breaks.break()
}
}
)
println("正常结束循环")
}
}
对breaks进行省略
object Demo_while {
def main(args: Array[String]): Unit = {
breakable(
for (emel <- 1 to 10) {
println(emel)
if (emel == 5) {
break()
}
}
)
println("正常结束循环")
}
}