scala省略原则:
1、当调用对象的方法时,点.可以省略
2、如果函数参数只有一个,或者没有参数,()可以省略
3、如果if代码只有一行,那么可以省略花括号
scala
1、scala源码中包含了main方法,在编译自动形成了public static void main
2、scala在编译源码时,会生成两个字节码文件,静态main方法执行另外一个字节码文件中的成员main方法
3、Scala是完全面向对象的语言,那么没有静态的语法,只能通过模拟生成静态方法
4、编译时将当前类生成一个特殊的类 ==》Scala01_HelloWorld$,然后创建对象来调用这个对象的main方法
5、在一般情况下,将加$对的类的对象,称为”伴生对象“
6、伴生对象中的内容,都可以通过类名访问,来模拟Java中的静态语法
7、伴生对象的语法规则,使用object声明
8、public static void main (String[] args){ 方法体 }
9、scala中的没有public关键字,默认所有的的访问权限都是公共的。
10、scala中没有void关键字,采用特殊的对象模拟,Unit。
11、Scala中声明方法采用关键字def
12、方法后面的小括号是方法的参数列表
13、Scala中的参数列表的声明方式和Java不一样
14、java: String 参数名,Java中是先考虑类型再写参数名
15、Scala:参数名:类型。Scala中是先写参数名再考虑类型
16、java中方法的声明和方法体直接连接
17、Scala中的方法的声明和方法体是通过”=“连接
18、Scala中将方法的返回值类型放置在方法声明的后面使用”:“连接
19、scala中的原则是:能省则省
object Scala01_HelloWorld {
def main(args: Array[String]): Unit = {
print("Hello World!")
}
}
scala程序开发注意事项
1、Scala语言严格区分大小写
2、Scala方法由一条条语句构成,每个语句后面不需要分号
3、如果在同一行有多条语句,除了最后一条语句不需要分号,其他语句需要分号
Scala语言输出的三种方式
object Scala02_StringPrint {
def main(args: Array[String]): Unit = {
val name = "ApacheCN"
val age = 1
val url = "www.alibaba.com"
}
1、字符串通过 + 号连接(类似Java)
print("name=" + name + "age=" + age + "url=" + url +"\n")
2、printf用法(类似C语言)字符串通过%传值。(格式化输出)
printf("name=%s,age=%d,url=%s\n",name, age,url)
3、字符串插值:通过$引用(类似PHP)
//使用原始值,原样输出
println(raw"name=${name},age=${age},url=${url}")
println(s"name=${name},age=${age},url=${url}")
//小数点后保留两位
println(f"name=${name},age=${age}%.2f,url=${url}")
object Scala02_StringPrint {
def main(args: Array[String]): Unit = {
//打印字符串
val name = "ApacheCN"
val age = 1
val url = "www.cw.com"
//字符串通过+号连接(类似java)
println("name=" + name + " age=" + age + " url=" + url)
//printf用法 (类似C语言)字符串通过 % 传值。
printf("name=%s, age=%d, url=%s \n", name, age, url)
//插值字符串:字符串通过$引用
println(s"name=${name}, age=$age, url=$url")
println(f"name=${name}, age=${age}%.2f, url=$url")
print(raw"name=${name}, age=${age}%.2f, url=$url \n")
}
}
注释
1、单行注释
使用”//“
2、多行注释
”/*
*/“
3、文档注释
”/**
*
**/“
scala核心编程
一、变量使用的基本步骤
1)声明/定义变量
语法:
val | var 变量名称:[变量类型] = 变量的值
var name:String = "小张"
var age:Int = 23
var c:Char = 'c'
2)使用
1、scala声明变量必须显示初始化
object ScalaVariable {
def main(args: Array[String]): Unit = {
var username // Error
val username = "zhangsan" // OK
}
}
2、使用"val"声明的变量的值无法修改,称之为不可变变量
object ScalaVariable {
def main(args: Array[String]): Unit = {
// 用户名称
val username : String = "zhangsan"
username = "lisi" // Error
username = true // Error
}
}
3、使用”var“修饰的变量的值可以进行修改,称之为可变变量
object ScalaVariable {
def main(args: Array[String]): Unit = {
// 用户名称
var username : String = "zhangsan"
username = "lisi" // OK
username = true // Error
}
}
4、在方法外部声明的变量如果采用val关键字,等同于使用final修饰
3)注意事项
1、声明变量时,类型可以省略(就叫类型判断)
2、类型确定后,就不能修改,说明Scala是强数据类型
3、在声明和定义一个变量时,可以使用var或者val来修饰,var修饰的变量可以改变,val修饰的变量不可以改
4、val修饰的对象属性在编译后,等同于加上final
5、var修饰的对象引用可以改变,val修饰的则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等)
object Scala01_Var_1 {
def main(args: Array[String]): Unit = {
// TODO scala为了让开发过程变得简单,可以将自动推断出来的内容省略
val name = "lisi"
val dog = new Dog()
dog.name = "xxxx"
// TODO var修饰的对象引用可以改变,val 修饰的则不可改变,但对象的状态(值)却是可以改变的。(比如: 自定义对象、数组、集合等等)
println(dog.name)
}
}
class Dog {
var name: String = ""
}
6、变量声明,必须有初始值(显示初始化)
object Scala01_Var {
// TODO 在方法的外部声明的变量如果采用val关键字,等同于使用final修饰
val sex: String = "男"
def main(args: Array[String]): Unit = {
// java局部变量
// int i = 10;
// scala声明变量
// TODO var 变量名称 : 变量类型 = 变量的值
// var name: String = "zhangsan"
// TODO scala声明变量必须显式的初始化
// var name:String
// name="zhangsan"
// TODO 使用var声明的变量的值是可以修改的
var age: Int = 10
var c: Char = 'C'
var b: Boolean = true
// TODO 使用val声明的变量的值无法修改
val name: String = "zhangsan"
}
}
二、scala数据类型
Scala与Java有着相同的数据类型,但是又有不一样的地方
1、scala是完全面向对象的语言,所以没有基本数据类型
2、Scala与Java有着相同的数据类型,在Scala中的数据类型都是对象,也就是说Scala没有Java的原生(基本)类型。
object Scala02_DataType {
def main(args: Array[String]): Unit = {
// TODO scala是完全面向对象的语言,所以没有基本数据类型
//Scala 与 Java有着相同的数据类型,在Scala中数据类型都是对象,也就是说scala没有java中的原生类型
// TODO scala中数字也是对象,可以调用方法
val age: Int = 20
// 基本数据类型: byte,short,int,long,double,float,boolean,char
val b: Byte = 10
val s: Short = 10
val i: Int = 10
val lon = 10000000000000L
val f: Float = 10.0f
val d: Double = 10
val bln: Boolean = true
val c: Char = 'c'
val ii: Integer = 10
val a: Any = 10
}
}
3、Scala数据类型分为两大类AnyVal(值类型)和AnyRef(引用类型)注意:不管是AnyVal和AnyRef都是对象
var num1: Int = 10
println(s"num1=${num1}")
var char1:Char = 'a'
print(s"char1=${char1}")
4、相对于Java的类型系统,Scala要复杂些!也正是这些复杂多变的类型系统才面向对象编程和函数式编程完美的融合在了一起
object Scala02_DataType {
def main(args: Array[String]): Unit = {
//数据类型
//Scala是完全面向对象的语言,所以没有基本数据类型
//在scala中数字也是对象,可以调用方法
val age: Int = 24
val b:Byte = 10
//在Scala中不用聲明它就是對象: 比如 10现在就是一个对象
}
}
Unit类型、Null类型、Nothing类型
Unit | 表示无值,和其他语言中的void等同,作用不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
---|---|
Null | null,Null类型只有一个实例值null |
Nothing | Nothing类型在Scala的类层级的最低端:它是任何其他类型的子类类型。当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回值的值(异常)赋给其它的函数或者变量(兼容性) |
def f1():nothing = {
throw new Exception()
}
使用细节和注意事项
1)Null类只有一个对象实例,null,类似于Java中的null引用。null可以赋值给任意引用类型(AnyRef),但是不能赋给值类型(AnyVal)(比如:int、Float、Char、Boolean、Long、Byte、Short)
2)Unit类型用来标识过程,也就是没有明确返回值的函数由此可见,Unit类似于Java里的viod,Unit只有一个实例,这个实例也没有实质的意义
3)Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。
import java.io.{File, PrintWriter}
object Scala11_DataType {
def main(args: Array[String]): Unit = {
// TODO Scala 数据类型
// Null表示空类型,只有一个对象为 null
val s : String = null
val i : Int = 20
println(s)
println(i)
// Unit表示方法没有返回值,只有一个对象,这个对象为:()
// Nothing表示没有正常值。
}
// def test() = {
// throw new Exception
// }
}
值类型转换
1、隐式类型转换
object ScalaDataType {
def main(args: Array[String]): Unit = {
val b : Byte = 10
val s : Short = b
val i : Int = s
val lon : Long = i
}
}
自动类型转换细节说明
1)多种类型的数据混合运算时,系统首先将所有数据转换成容量最大的那种数据类型,然后再进行计算
2)当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据类型时,就会报错,反之就会进行自动类型转换
-
(byte,short)和char之间不会互相自动转换
-
byte,short,char它们三者可以计算,在计算时首先转换为Int类型
-
自动提升原则:表达式结果的类型自动提升操作数中最大类型
2、强制类型转换
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换函数,但可能造成精度降低或溢出,格外注意。
java: int num = (int)2.5
scala: var num:int = 2.7.toInt
-
当进行数据的从大---------->小,就需要使用到强制类型转换
-
强制符号只针对于最近的操作有效,往往会使用小括号提升优先级
var num:Int = 10 * 3.5.toInt + 6 * 1.5.toInt
var num:Int = (10 * 3.5 + 6 * 1.5).toInt
-
Char类型可以保存Int的常量值,但不能保存Int的变量值,需要转换
-
Byte和Short类型在进行运算时,当做Int类型处理
object Scala02_DataType2 {
def main(args: Array[String]): Unit = {
// TODO byte,short,char 他们三者可以计算,在计算时首先转换为int类型。
var s: Short = 5 // ok
//s = s-2 // error Int -> Short
var b: Byte = 3 // ok
//b = b + 4 // error Int ->Byte
//b = (b + 4).toByte // ok ,使用强制转换
//var c: Char = 'a' // ok
//var i: Int = 5 // ok
//var d: Float = .314F // ok
// TODO 自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型
//var result: Double = c + i + d //ok Float->Double
//var b: Byte = 5 // ok
//var s: Short = 3 // ok
//var t : Short = s + b // error Int->Short
//var t2 = s + b // ok, 使用类型推导
}
}
3、值类型和String类型的转换
1、基本类型转String类型(java)
String str1 = true + "";
String str2 = 4.5 + "";
String str3 = 100 + "";
2、String类型转基本数据类型类型
s1.toInt
s1.toFloat
s1.toDouble
s1.toByte
s1.toLong
s1.toShort
三、标识符
Scala 可以使用两种形式的标志符,字符数字和符号。
1、scala中可以使用特殊符号作为标识符,其实是将特殊符号在编译时进行了转换。
val ++ = "123"
println(++)
val +-*/ = 123
println(+-*/)
val %@# = true
println(%@#)
2、scala中的下划线_有特殊的用途,不能独立当成变量名来使用
val _ = "123"
val a = "abc" + _
println(a)
3、用反引号‘…’包括的任意字符串,即使是关键字(39个)也可以 [true]
val `private` = 123
println(`private`)
习题:
// 和Java一样的标识符命名规则
val name = "zhangsan" // OK
val name1 = "zhangsan0" // OK
//val 1name = "zhangsan0" // Error
val name$ = "zhangsan1" // OK
val $name = "zhangsan2" // OK
val name_ = "zhangsan3" // OK
val _name = "zhangsan4" // OK
val $ = "zhangsan5" // OK
val _ = "zhangsan6" // OK
//val 1 = "zhangsan6" // Error
//val true = "zhangsan6" // Error
// 和Java不一样的标识符命名规则
val + = "lisi" // OK
val - = "lisi" // OK
val * = "lisi" // OK
val / = "lisi" // OK
val ! = "lisi" // OK
//val @ = "lisi" // Error
val @@ = "lisi" // OK
//val # = "lisi" // Error
val ## = "lisi" // OK
val % = "lisi" // OK
val ^ = "lisi" // OK
val & = "lisi" // OK
//val ( = "lisi" // Error
//val ( = "lisi" // Error
//val ) = "lisi" // Error
//val = = "lisi" // Error
val == = "lisi" // OK
//val [ = "lisi" // Error
//val ] = "lisi" // Error
//val : = "lisi" // Error
val :: = "lisi" // OK
//val ; = "lisi" // Error
//val ' = "lisi" // Error
//val " = "lisi" // Error
val "" = "lisi" // OK
val < = "lisi" // OK
val > = "lisi" // OK
val ? = "lisi" // OK
val | = "lisi" // OK
val \ = "lisi" // OK
//val ` = "lisi" // Error
val ~ = "lisi" // OK
val :-> = "wangwu" // OK
val :-< = "wangwu" // OK
// 切记,能声明和能使用是两回事
四、字符串
在 Scala 中,字符串的类型实际上是 Java String,它本身没有 String 类。
在 Scala 中,String 是一个不可变的对象,所以该对象不可被修改。这就意味着你如果修改字符串就会产生一个新的字符串对象。
object ScalaString {
def main(args: Array[String]): Unit = {
val name : String = "scala"
val subname : String = name.substring(0,2)
}
}
1、字符串连接
object ScalaString {
def main(args: Array[String]): Unit = {
// 字符串连接
val name:String = "scala"
println("Hello " + name)
}
}
2、传值字符串
object ScalaString {
def main(args: Array[String]): Unit = {
// 传值字符串(格式化字符串)
val name:String = "scala"
printf("name=%s\n", name)
}
}
3、插值字符串
object ScalaString {
def main(args: Array[String]): Unit = {
// 插值字符串
// 将变量值插入到字符串
val name:String = "scala"
println(s"name=$name")
}
}
4、多行字符串
object ScalaString {
def main(args: Array[String]): Unit = {
// 多行格式化字符串
// | 默认顶格符
val name:String = "scala"
println(
s"""
| Hello
| ${name}
""".stripMargin)
}
}
五、输入输出
1、从屏幕获取输入
object ScalaIn {
def main(args: Array[String]): Unit = {
// 标准化屏幕输入
val age : Int = scala.io.StdIn.readInt()
println(age)
}
}
2、从文件中获取输入
import scala.io.Source
object Scala09_Input1 {
def main(args: Array[String]): Unit = {
// TODO Scala 输入
// 从文件中获取输入数据
// 文件路径可以为绝对路径:c:\test
// 文件路径可以为相对路径:input/word.txt
// Scala使用IDEA开发时,相对文件路径是以project的根目录为基准进行查找的。
val lines: Iterator[String] = Source.fromFile("input/word.txt").getLines()
while ( lines.hasNext ) {
println(lines.next())
}
}
}
3、输出
Scala进行文件写操作,用的都是Java中的I/O类
import java.io.{File, PrintWriter}
object ScalaOut {
def main(args: Array[String]): Unit = {
val writer = new PrintWriter(new File("C:\\Users\\ming\\Desktop\\b.txt"))
writer.write("滚滚长江东逝水")
writer.close()
}
}
六、运算符
scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。
1、算数运算符
假定变量A为10,B为20
运算符 | 描述 | 实例:运算结果 |
---|---|---|
+ | 加号 | A+B=30 |
- | 减号 | A-B=-10 |
* | 乘号 | A*B=300 |
/ | 除号 | B/A=2 |
% | 求余 | B/A=0 |
2、关系运算符
假定变量A为10,B为20
运算符 | 描述 | 实例:运算结果 |
---|---|---|
== | 等于 | (A == B)运算结果为:false |
!= | 不等于 | (A != B)运算结果为:true |
> | 大于 | (A > B)运算结果为:false |
< | 小于 | (A < B)运算结果为:true |
>= | 大于等于 | (A >= B)运算结果为:false |
<= | 小于等于 | (A <= B)运算结果为:true |
3、赋值运算符
运算符 | 描述 | 实例:运算结果 |
---|---|---|
= | 简单的赋值运算,指定右边操作数赋值给左边的操作数 | C = A + B |
+= | 相加再赋值,将左右两边的操作数相加后赋给左边的操作数 | C += A相当于 C = C+A |
-= | 相减再赋值,将左右两边的操作数相减后赋给左边的操作数 | C -= A相当于 C = C-A |
*= | 相乘再赋值,将左右两边的操作数相乘后赋给左边的操作数 | C = A相当于 C = CA |
/= | 相处再赋值,将左右两边的操作数相除后赋给左边的操作数 | C /= A相当于 C = C/A |
%= | 求余再赋值,将左右两边的操作数求余后赋给左边的操作数 | C %= A相当于 C = C%A |
<<= | 按位左移后再赋值 | C << =2 相当于C = C << 2 |
>>= | 按位右移后再赋值 | C >> =2 相当于C = C >> 2 |
&= | 按位与运算再赋值 | C & =2 相当于C = C & 2 |
^= | 按位异或运算后再赋值 | C ^= 2 相当于C = C ^ 2 |
|= | 按位或移运算后再赋值 | C |= 2 相当于C = C | 2 |
4、逻辑运算符
假定变量A 为 1,B为0
运算符 | 描述 | 实例:运算结果 |
---|---|---|
&& | 逻辑与 | (A&&B)结果:false |
|| | 逻辑或 | (A||B)结果:true |
! | 逻辑非 | !(A&&B)结果:true |
5、位运算符
如果指定A=60;B=13
A=0011 1100
B=0000 1101
运算符 | 描述 | 实例:运算结果 |
---|---|---|
& | 按位与运算符 | (A&B)= 12, 二进制:0000 1100 |
| | 按位或运算符 | (A|B)= 61, 二进制:0011 1101 |
^ | 按位异或运算符 | (A&B)= 49, 二进制:0011 0001 |
~ | 按位取反运算符 | (~A)= -61, 二进制:1100 0011 |
<< | 左移动运算符 | (A<<2)= 120, 二进制:1111 0000 |
>> | 右移动运算符 | (B>>2)= 1, 二进制:0000 1100 |
>>> | 无符号右移 | (A>>>2)= 15, 二进制:0000 1111 |
6、运算符本质
在Scala中其实是没有运算符的,所有运算符都是方法。
1、 scala是完全面向对象的语言,所以数字其实也是对象
2、当调用对象的方法时,点.可以省略
3、如果函数参数只有一个,或者没有参数()可以省略
object Scala16_Operator1 {
def main(args: Array[String]): Unit = {
// TODO Scala 是一个完全面向对象的语言
// 声明数字1其实不是一个数字,而是一个数值对象
// 所谓的运算符其实就是对象的方法
//val num = 1.+(1)
//val num = 1 +(1)
//val num = 1 + 1
val i : Int = 10
// Scala至简原则:能省则省
println(i toString)
}
}
第四章 流程控制
一、分支控制
让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支
1.1、单分支
IF…ELSE 语句是通过一条或多条语句的执行结果(true或者false)来决定执行的代码块
语法:
if(布尔表达式) {
// 如果布尔表达式为 true 则执行该语句块
}
如果布尔表达式为 true 则执行大括号内的语句块,否则跳过大括号内的语句块,执行大括号之后的语句块。
object Scala01_Control {
def main(args: Array[String]): Unit = {
// TODO Scala 流程控制
// 单分支
//
val name = "zhangsan"
// if ( name == "zhangsan" ) {
// println("name is zhangsan")
// }
// java中的双等号表示值是否相等,如果是引用类型,那么引用类型的值
// java中一般字符串的比较都是使用equals,而不是使用双等号
// scala语言中的双等号其实是比较字符串的内容
//if ( name == new String("zhangsan") ) {
//if ( name.equals(new String("zhangsan")) ) {
// scala语言中的eq其实是比较字符串的地址
// eq在编译后其实就是java中的双等号
if ( name eq new String("zhangsan") ) {
println("name is zhangsan")
}
}
}
1.2、双分支
语法:
if(布尔表达式) {
// 如果布尔表达式为 true 则执行该语句块
} else {
// 如果布尔表达式为 false 则执行该语句块
}
如果布尔表达式为 true 则执行接着的大括号内的语句块,否则执行else后的大括号内的语句块。
object Scala02_Control1 {
def main(args: Array[String]): Unit = {
// TODO Scala 流程控制
// 双分支
//
// val name = "zhangsan"
//
// if ( name eq new String("zhangsan") ) {
// println("name is zhangsan")
// } else {
// println("name is not zhangsan")
// }
// true? code : code
// Scala中没有三元运算符,使用if...else语法代替
// java中三元运算符
// int i = 20
// int j = i == 20 ? 30 : 40
// val i = 10
// var j = 0
// if ( i == 20 ) {
// //println("20")
// j = 30
// } else {
// //println("30")
// j = 40
// }
// Scala中所有的表达式都有返回结果
// Scala中会将满足条件的最后一条代码作为表达式的返回结果
// 如果if代码只有一行,那么可以省略花括号
val i = 50
var result = if (i < 30) {
30
//"zhangsan"
} else {
40
}
println("***************")
result = if (i < 30) 30 else 40
println("result = " + result)
}
}
object Scala03_Control2 {
def main(args: Array[String]): Unit = {
// TODO Scala 流程控制
val age = 30
// Scala也是静态类型语言,需要在编译时确定变量的类型
// 所以如果不执行逻辑就想要确定类型,那么就必须使用通用父类型
val result = if ( age < 30 ) {
20 // Int
"zhangsan" // String
} else {
40 // Int
null // Null
}
println("result = " + result)
}
}
1.3、多分支
语法:
if(布尔表达式1) {
// 如果布尔表达式1为 true,则执行该语句块
} else if ( 布尔表达式2 ) {
// 如果布尔表达式2为 true,则执行该语句块
}...
} else {
// 上面条件都不满足的场合,则执行该语句块
}
习题:实现一个小功能:输入年龄,如果年龄小于18岁,则输出“童年”。如果年龄大于等于18且小于等于30,则输出“青年”,如果年龄大于30小于等于50,则输出”中年”,否则,输出“老年”。
object Scala04_Control3 {
def main(args: Array[String]): Unit = {
// TODO Scala 流程控制
val age : Int = 60
val result = if ( age < 18 ) {
println("少年") // Unit
} else if ( age < 36 ) {
println("青年")// Unit
} else if ( age < 55 ) {
println("壮年")// Unit
} else {
//println("老年")// Unit
"老年"
}
println("result = " + result)
}
}
二、循环控制
Scala语言提供了以下几种循环类型 :
for循环、while循环、do…while循环
1、for循环
1)基本语法
for ( 循环变量 <- 数据集 ) {
循环体
}
这里的数据集可以是任意类型的数据集合,如字符串、集合、数组等。
object Scala05_Control4 {
def main(args: Array[String]): Unit = {
// TODO Scala 流程控制
/*
java :
for ( int i = 0; i < 10; i++ ) {
sout("i = " + i)
}
for ( int i : list ) {
sout("i = " + i)
}
*/
// Scala 循环, 类似于java中的增强for循环
/*
for ( 循环变量 <- 数据集 ) {
循环体
}
*/
for ( i <- Range(1,5) ) { // 不包含5
println("i = " + i)
}
for ( j <- 1 to 5 ) { // 包含5
println("j = " + j)
}
for ( k <- 1 until 5 ) { // 不包含5
println("k = " + k)
}
}
}
2)循环守卫
循环时可以增加条件来决定是否继续循环体的执行,这里的判断条件我们认为是循环的守卫
object ScalaLoop {
def main(args: Array[String]): Unit = {
for ( i <- Range(1,5) if i != 3 ) {
println("i = " + i )
}
}
}
3)循环步长
scala的集合也可以设定循环的增长幅度,也就是所谓的步长step
object ScalaLoop {
def main(args: Array[String]): Unit = {
for ( i <- Range(1,5,2) ) {
println("i = " + i )
}
for ( i <- 1 to 5 by 2 ) {
println("i = " + i )
}
}
}
4)循环嵌套
object ScalaLoop {
def main(args: Array[String]): Unit = {
//简化版
for ( i <- Range(1,5): j <- Range(1,4) ) {
println("i = " + i + ",j = " + j )
}
//普通版
for ( i <- Range(1,5) ) {
for ( j <- Range(1,4) ) {
println("i = " + i + ",j = " + j )
}
}
}
}
5)引入变量
object ScalaLoop {
def main(args: Array[String]): Unit = {
for ( i <- Range(1,5): j = i - 1 ) {
println("j = " + j )
}
}
}
6)返回值
scala所有的表达式都是有返回值的。但是这里的返回值并不一定都是有值的哟。
如果希望for循环表达式的返回值有具体的值,需要使用关键字yield
object ScalaLoop {
def main(args: Array[String]): Unit = {
val result = for ( i <- Range(1,5) ) yield {
i * 2
}
println(result)
}
2、while循环
1)基本语法
当循环条件表达式返回值为true时,执行循环体代码
while( 循环条件表达式 ) {
循环体
}
一种特殊的while循环就是,先执行循环体,再判断循环条件是否成立
do {
循环体
} while ( 循环条件表达式 )
2)while循环
object ScalaLoop {
def main(args: Array[String]): Unit = {
var i = 0
while ( i < 5 ) {
println(i)
i += 1
}
}
}
3)do…while循环
object ScalaLoop {
def main(args: Array[String]): Unit = {
var i = 5
do {
println(i)
} while ( i < 5 )
}
}
3、循环中断
scala是完全面向对象的语言,所以无法使用break关键字这种方式来中断循环逻辑,而是采用了函数式编程的方式代替了循环语法中的break和continue
scala.util.control.Breaks._
object ScalaLoop {
def main(args: Array[String]): Unit = {
scala.util.control.Breaks.breakable {
for ( i <- 1 to 5 ) {
if ( i == 3 ) {
scala.util.control.Breaks.break
}
println(i)
}
}
}
4、嵌套循环
练习题:
*
***
*****
*******
*********
***********
*************
***************
*****************
object Scala04_Control6 {
def main(args: Array[String]): Unit = {
for (i <- 1 to 18 by 2; j = (18-i)/2){
println(" " * j + "*" * i)
}
}
}
第五章 函数式编程
1、面向对象编程
分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题
2、函数式编程
将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。
一、基础函数式编程
1、基本语法
[修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = {
函数体
}
private def test( s : String ) : Unit = {
println(s)
}
2、函数&方法
1)scala 有方法与函数的概念,二者在语义上的区别很小。scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。scala 中的方法跟 Java 的类似,方法是组成类的一部分。scala 中的函数则是一个完整的对象
2)Scala中的方法和函数一般不好区分,所以简单的理解就是:方法也是函数。只不过类中声明的函数就称之为方法,而类中的方法是有重载和重写的。其他场合声明的就是函数了,那可就没有重载和重写的概念哦,而且函数是可以嵌套声明使用的,但是方法就没有办法声明方法了,千万记得哟。
object Scala02_Function1 {
def main(args: Array[String]): Unit = {
// TODO 函数式编程
// 函数 & 方法
// 在Scala中,方法其实就是函数,一般将类中的函数称之为方法
// 其他的场合就是函数
// 函数
// Scala的语法结构比较松散,任意一个语法结构可以声明其他语法
// 方法中可以有函数
// 函数中可以声明函数
def test1(): Unit = {
def test2(): Unit = {
}
}
def test4(s:String): Unit = {
}
// 方法是可以重写和重载的。
// 函数没有重写和重载的概念。
}
// 方法
def test3(): Unit = {
}
// 重载方法
def test3(s:String): Unit = {
}
}
3、函数定义
1)无参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): Unit = {
println("函数体")
}
fun1()
}
}
2)无参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2(): String = {
"zhangsan"
}
println( fun2() )
}
}
3)有参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3( name:String ): Unit = {
println( name )
}
fun3("zhangsan")
}
}
4)有参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4(name:String): String = {
"Hello " + name
}
println( fun4("zhangsan") )
}
}
5)多参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(hello:String, name:String): Unit = {
println( hello + " " + name )
}
fun5("Hello", "zhangsan")
}
}
6)多参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun6(hello:String, name:String): String = {
hello + " " + name
}
println( fun6("Hello", "zhangsan"))
}
}
4、函数参数
函数的参数最多只能声明22个
1)可变参数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun7(names:String*): Unit = {
println(names)
}
fun7()
fun7( "zhangsan" )
fun7( "zhangsan", "lisi" )
}
}
可变参数不能放置在参数列表的前面,一般放置在参数列表的最后
oobject ScalaFunction {
def main(args: Array[String]): Unit = {
// Error
//def fun77(names:String*, name:String): Unit = {
//}
def fun777( name:String, names:String* ): Unit = {
println( name )
println( names )
}
}
2)参数默认值
object Scala04_Function3 {
def main(args: Array[String]): Unit = {
// TODO 函数式编程
// TODO 参数默认值
// 给所有的用户默认密码
// 函数的参数默认使用val声明,无法修改
//def f1( password:String, name:String* ): Unit = {
// if ( password == null ) {
// password = "000000"
// }
// var pswd = ""
// if ( password == null ) {
// pswd = "000000"
// } else {
// pswd = password
// }
//}
// Scala中提供了参数默认值
// 如果参数设定了默认值,那么调用函数时,可以不用传递这个参数
// def f2( name : String, password : String = "000000" ): Unit = {
// println( s"name = ${name}, password = ${password}" )
// }
// 调用函数时,如果传递了指定的参数,那么会覆盖默认值
//f2("zhangsan", "123123")
// f2("zhangsan")
def f3( password:String = "000000", name:String ): Unit = {
println( s"name = ${name}, password = ${password}" )
}
//f3("123123", "zhangsan")
// 函数的参数传值方式为:从前到后,从左到右
//f3("zhangsan")
// TODO 带名参数
// 传递函数参数的时候,同时指明参数的名称
f3( name="zhangsan" )
}
}
3)带名参数
// TODO 带名参数
// 传递函数参数的时候,同时指明参数的名称
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun9( password:String = "000000", name:String ): Unit = {
println( name + "," + password )
}
fun9("123123", "zhangsan" )
fun9(name="zhangsan")
}
}
5、函数至简原则
所谓的至简原则,其实就是Scala的编译器为了提高开发效率。帮助我们将函数声明中能简化的地方全部都进行了简化。也就是说将函数声明中那些能省的地方全部都省掉。所以简单来说就是:能省则省
1)省略return关键字
函数可以使用最后一行代码作为函数返回值,return关键字可以省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): String = {
return "zhangsan"
}
def fun11(): String = {
"zhangsan"
}
}
}
2)省略”{}“花括号
如果函数体中的代码只有一行,那么可以省略花括号
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2(): String = "zhangsan"
}
}
3)省略”()“小括号
如果函数的参数列表是无参的,那么调用时可以省略小括号
object ScalaFunction {
def main(args: Array[String]): Unit = {
def f3 : String = "wangwu"
//val name : String = "zhangsan"
// 如果函数省略了参数列表,那么调用时不能增加小括号
// 为了访问一致性
//println( f3() ) // Error
//println( f3 ) // OK
}
}
4)省略返回值类型
如果函数的返回值类型能够推断出来,那么也可以省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3() = "zhangsan"
}
}
5)省略参数列表
如果函数声明中没有参数,那么参数列表的小括号可以省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4 = "zhangsan"
}
}
6)省略”=“等号
如果省略返回值类型,那么编译器会将函数体的最后一行代码最为返回值
如果函数体中明确使用return关键字,那么返回值类型不能省略
如果函数明确声明Unit,那么即使函数体中有return语法也不起作用。
如果函数想要无返回值,但是又想省略Unit类型,那么可以使用省略等号的方式
将没有返回值类型和等号的函数称之为***过程函数***
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(): String = {
return "zhangsan"
}
println(fun5())
}
}
7)省略名称和关键字
如果函数只关心调用,而不关心名称,那么def关键字和函数名可以省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
// 如果函数没有def关键字和函数名,那么称之为匿名函数
// 小括号表示参数列表,不能省略, => 表示指向函数体
// 如果匿名函数想要调用,必须有名称,可以将匿名函数赋值给变量进行调用
() => {
println("zhangsan")
}
//调用
//val t = () => {println("zhangsan")}
//t()
}
}