一 相关知识
1.1 scala的安装
1.在idea中导入依赖,并在Idea下载scala插件
1.2 scala基础知识点
1.scala代码中一行语句的结束是以换行符为标准,可以不用写分号
2.class是一个普通的类,object相当于一个单例对象,object类中的方法相当于加上一个static关键字
二 基础知识
2.1 基本数据类型
Byte、Short、Int、Long、Float、Double、Char、Boolean
2.2 定义变量常量
var 变量名:数据类型=数值
val 变量名:数据类型=数值
注意:定义了变量后续使用不需要指明类型
package com.shujia.day01
object Demo1 {
def main(args: Array[String]): Unit = {
println("hello world")
var a: Int = 10
val b: Int = 19
var c: String = "hello"
println(a)
println(b)
}
}
2.3 获取数据类型
变量名.getClass 或者 变量名.getClass.getSimpleName方法查看数据类型
package com.shujia.day01
object Demo1 {
def main(args: Array[String]): Unit = {
println("hello world")
var a: Int = 10
val b: Int = 19
var c: String = "hello"
println(a)
println(b)
println(a.getClass.getSimpleName) //int
println(c.getClass)//class java.lang.String
}
}
2.4 字符串拼接
1.scala提供了一个方法类似拼接的方式语法 s"${xx}"
package com.shujia.day01
object Demo1 {
def main(args: Array[String]): Unit = {
println("hello world")
var a: Int = 10
val b: Int = 19
var c: String = "hello"
println(a)
println(b)
println(a.getClass.getSimpleName) //int
println(c.getClass)//class java.lang.String
var str:String=s"${a}|${b}"
println(str)//10|19
}
}
2.数组里面有个方法可以将数组里面的元素拼接
数组.mkString(拼接符号)
2.5 控制语句
2.5.1 选择语句
if else语句
package com.shujia.day01
import java.util.Scanner
object Demo2 {
def main(args: Array[String]): Unit = {
val sc: Scanner = new Scanner(System.in)
println("请输入您的年龄")
val age: Int = sc.nextInt()
if(age<18){
println("未成年")
}else{
println("成年")
}
}
}
while 循环
注意 :scala里面不支持++与--的
package com.shujia.day01
import java.util.Scanner
object Demo2 {
def main(args: Array[String]): Unit = {
val sc: Scanner = new Scanner(System.in)
println("请输入您的年龄")
val age: Int = sc.nextInt()
if(age<18){
println("未成年")
}else{
println("成年")
}
val array1: Array[Int] = Array(11, 22, 33, 44, 55)
var i: Int = 0
while (i<array1.length){
println(array1(i))
i += 1
}
}
}
2.5.2 循环语句
1.注意Scala里面没有for循环,他只适用于遍历各个容器
2.容器for循环
val array1: Array[Int] = Array(11, 22, 33, 44, 55)
var i: Int = 0
while (i<array1.length){
println(array1(i))
i += 1
}
for (elem <- array1) {
println(elem)
}
3.不是容器的for循环
to:表示可以取到右边的
util:表示取不到右边的
for (e <- 1 to 10){
println("hello world")
}
for (e <- 1 until 10){
println("hello world")
}
2.5.3 控制条件
1.Scala里面的break countie 是没有的需要导包
import scala.util.control.Breaks._ // _相当于java中的*
2.Scala里面break 需要抛出异常
breakable{
for (e <- 1 until 10){
if (e==5){
break
}
println(e)
}
}
2.6 IO流
2.6.1 读文件
1.Scala里面有一个 Source类 读取文件
2.Source的对象的getLines获取的是迭代器对象
package com.shujia.day01
import scala.io.{BufferedSource, Source}
object Demo3IO {
def main(args: Array[String]): Unit = {
//获取文件对象
val bs: BufferedSource = Source.fromFile("scala/data/demo")
//创建读文件的迭代器
val lines: Iterator[String] = bs.getLines()
for (elem <- lines) {
println(elem)
}
}
}
2.6.2 写文件
1.Scala里面木单独的类写文件,只能依靠Java里面的方法
val bw = new BufferedWriter(new FileWriter("scala/data/out1.txt"))
bw.write("hello world1")
bw.newLine()
bw.write("hello world2")
bw.close()
2.7 函数
2.7.1函数的定义
1.定义在object里面的叫函数,定义在class里面的叫方法
2.主函数
* def: 定义函数或者方法的关键字
* main: 函数名 main函数是被java虚拟机所特有识别的程序入口
* args: 参数名
* Array[String]: 参数的数据类型
* Unit: 返回值类型 相当于java中的void
3.函数可以在object任意一个位置定义
2.7.2 函数的调用
在object对象内部,函数相当于加了一个static,将来调用的时候,可以使用object对象名进行调用
在同一作用域中,调用时可以不加对象名
package com.shujia.day02
object Demo4Func {
def main(args: Array[String]): Unit = {
/** def: 定义函数或者方法的关键字
* main: 函数名 main函数是被java虚拟机所特有识别的程序入口
* args: 参数名
* Array[String]: 参数的数据类型
* Unit: 返回值类型 相当于java中的void
*/
println(add(2,4))
println(Demo4Func.add(2,4))
}
//定义一个add函数
def add(a:Int,b:Int):Int={
return a+b
}
}
2.7.3 函数的简写
1、如果函数体中最后一行语句作为返回值的时候,return可以省略不写
2、如果函数体中只有一行语句实现,那么大括号也可以不用编写
3、函数的返回值可以进行自动类型推断,可以省略不写
4、如果函数没有参数列表的话,()也可以省略不写,def add5 = println("好好学习,天天向上")
//函数最后一句是返回的话,return可以不写
def add1(x: Int, y: Int): Int = {
x + y
}
//如果函数体中只有一行语句实现,那么大括号也可以不用编写
def add2(x:Int,y:Int):Int=x+y
//函数的返回值可以进行自动类型推断,可以省略不写
def add3(x:Int,y:Int)=x+y
//如果函数没有参数列表的话,()也可以省略不写
def add4=println("hello")
5.如果函数只有一个参数,那么调用的时候可以简写
直接所属object 方法名 参数
def add6(x: Int): Int = {
x+200
}
println(Demo4Func add6 3)
2.7.4 函数的递归
def jieCheng(i: Int): Int = {
if (i == 1) {
1
} else {
i * jieCheng(i - 1)
}
}
2.6 异常
1.scala默认处理异常的方式是向外抛,如果出错,后续代码不会执行
2.scala处理异常的另一种方式和java一样,也是try..catch..但是和java的写法不太一样
package com.shujia.day02
import java.io.FileNotFoundException
object Demo5Exception {
def main(args: Array[String]): Unit = {
try {
// val br = new BufferedReader(new FileReader("scala/data/sssss")) // FileNotFoundException
// val array1: Array[Int] = Array(11, 22, 33) // ArrayIndexOutOfBoundsException
// println(array1(4))
Class.forName("com.shujia.Demo")
} catch {
//模式匹配
case e:FileNotFoundException => println("文件找不到异常")
case e:ArrayIndexOutOfBoundsException => println("数组索引越界异常")
// case e:Exception => e.printStackTrace()
case _ => println("其他异常")
}finally {
//无论有没有对应的case捕获,都会执行
println("finally")
}
println("over")
}
}
3.其中的匹配模式在后面会说到
三 进阶知识
3.1 类与对象
3.1.1相关知识
1.有一个共同的父类 object
2.使用单例对象
3.1.2 构造方法
1.在new对象的时候,构造方法必须手动创造,并重载,并放在开头写
class Student {
println("好好学习天天向上")
def this(x:Int,y:Int) {
this()
println(x+y)
}
}
object Demo6Object {
def main(args: Array[String]): Unit = {
val student = new Student(10,20)
}
}
//好好学习天天向上
30
3.1.3 成员变量
1.创建成员变量默认语法
var _变量名:类型=_
2._表示占位符,将来可以传值进去
package com.shujia.day02
class Student2 {
//定义成员变量
private var _name: String = _
private var _age: Int = _
//构造方法
def this(name:String,age:Int) {
this()
this._name=name
this._age=age
}
override def toString = s"姓名${_name},年龄${_age}"
}
3. 私有成员变量
不提供get set方法 需要我们自己写
set有参数无返回值,get无参数有返回值
package com.shujia.day02
class Student2 {
//定义成员变量
private var _name: String = _
private var _age: Int = _
//构造方法
def this(name:String,age:Int) {
this()
this._name=name
this._age=age
}
//只有一条语句大括号可以省略
def setName(name:String):Unit =this._name
//没有参数 小括号可以不用写
def getName:String=this._name
def setAge(age:Int):Unit=this._age
def getAge: Int =this._age
override def toString = s"姓名${_name},年龄${_age}"
}
4.创建类的时候 传参
package com.shujia.day02
class Student3 (name:String,age:Int){
//定义成员变量
private var _name: String = name
private var _age: Int = age
private var _ad:String=_
def this(name:String,age:Int,ad:String) {
this(name,age)
this._ad=ad
}
override def toString = s"姓名${_name},年龄${_age},地址${_ad}"
}
这个在new对象的时候可以传2个值页可以传三个值,如果是两个值,定义class时没有传入的默认是null值,
3.1.4 成员方法
太简单 不说了
3.2 继承
跟java差不多,无需多言
3.3 伴生对象
1.object与class 创建的类的名字相同,class创建的类叫伴生对象
2.object创建的对象无法new出来。但是可以通过apply方法创建对象
package com.shujia.day02
object Demo7Apply {
def main(args: Array[String]): Unit = {
val phone2 = new Phone2("华为", 8000)
println(phone2)
val phone1: Phone2 = Phone.apply("苹果", 10000)
println(phone1)
}
}
object Phone {
def apply(kind: String, price: Int): Phone2 = new Phone2(kind, price)
}
class Phone2(kind: String, price: Int) {
override def toString = s"品牌:${kind}, 价格:${price}"
}
3.4 样例类
1.与普通的类的区别:
普通的类需要重写toString方法才能获取值,要不然打印的是地址值
默认不能修改值,需要修改,将case定义类的时候用var
2.在case定义类的时候可以暂时给定一个默认值用var修饰,后面创建对象的时候可以改
package com.shujia.day02
object Demo8Cass {
def main(args: Array[String]): Unit = {
val u1 = new User("慌", 19)
println(u1)//com.shujia.day01.User@2a18f23c
u1.ad="安全"
println(u1)
}
}
//class User(name:String,age:Int)
case class User(var str: String, i: Int,var ad:String="合肥");
四 面向函数式编程
4.1 函数作为参数
4.1.1 基础知识
1.将函数看作对象
2.使用 =>确定类型
4.1.2 函数作为值复制给变量
package com.shujia.day02
object Demo9Func {
def main(args: Array[String]): Unit = {
//创建一个函数将字符串变成int类型
def strToInt(str:String):Int={
str.toInt
}
val i1: Int = strToInt("1000")
println(i1)//1000
//定义一个变量接收这个函数,刚刚好这个变量的类型也是字符串变成int类型
val strToIntTemp : String=>Int =strToInt
val i2: Int = strToIntTemp("2000")
println(i2)//2000
}
}
4.1.3 参数是函数的函数
1.传入的是参数是啥类型的函数,啥类型是你目标参数需要的
//定义一个参数是函数的函数
/**
* 定义了一个fun函数,函数的参数是一个参数为String类型返回值是Int类型的函数
*/
def fun(f:String=>Int):Unit={
val i3: Int = f("3000")
println("这是fun函数")
println(i3)
}
//定义一个参数是String类型的,返回值是Int类型的函数
def method1(str:String):Int={
println("这是method1函数")
str.toInt+1000
}
//调用fun函数
fun(method1)
4.1.4 使用匿名函数改写
没有名字的函数
语法:
(参数列表)=> 返回值类型
1.匿名函数可以用一个变量接收,然后再传入主体函数中
2.匿名函数的返回值类型可以自动判断,不需要标明,标明就错了
3.当主体函数只有一句话的时候,可以直接传入匿名函数
4.匿名函数的参数类型也可以不写,但是会有警告,最好写上
5.当匿名函数中传入的参数只用了一次,且主体函数只有一句话的时候,可以用下划线代替匿名函数的参数
//创建匿名函数
//val f1: String => Int 定义了一个变量是类型是String转化成Int类型
//(s: String) => s.toInt 创建了一个匿名函数,这函数的作用就是将String变成Int
//(s: String) => s.toInt 这里的匿名函数也是简写的,因为函数的主体只有一句话,可以省区大括号,如果还想添加其他的,要加上大括号
//(s: String) => s.toInt 在匿名函数中 返回值的类型不需要写,会自动判断的
// val f1: String => Int = (s: String):Int => {s.toInt}//这样会报错
val f1: String => Int = (s: String) => {s.toInt}
//调用fun函数
fun("80",f1)
//当函数只有一行的时候,可以直接传入匿名函数
fun("88",(s:String)=>{s.toInt})
//lambda表达式的参数类型可以进行自动推断,不推荐这样,因为会有警告,最好加入匿名函数的参数类型
fun("22", s => s.toInt)
//如果传入的函数参数有且仅只用了一次的话,可以直接使用_代替
fun("22", _.toInt)
4.1.5 实例
package com.shujia.day02
object Demo10Func {
def main(args: Array[String]): Unit = {
//定义一个数组
val array: Array[Int] = Array(11, 22, 33, 44, 55, 66, 77, 88, 99)
//1 之前的for遍历数组
for (elem <- array) {
println(elem)
}
println("="*100)
//使用foreach函数遍历
//f: A => U ,参数是有类型的,返回值无类型的
array.foreach(f)
//定义一个函数f,参数是有类型的,返回值无类型的
def f(i:Int): Unit ={
println(i)
}
println("="*100)
//使用匿名函数
array.foreach((i:Int)=>{println(i)})
//参数类型不写
// array.foreach(i=>{println(i)})//会有警告,最好加上类型
//用_代替参数
array.foreach(println(_))
//使用Scala自动any类中的方法
//以后遍历数组就这样写
array.foreach(println)
}
}
4.2 函数作为返回值
4.2.1 参数与返回值都是函数
1.调用函数得到也是一个函数
//定义一个参数类型是String->Int的函数,返回值是一个参数列表为String->Int类型的函数
def fun(f:String=>Int):String=>Int={
println("好好学习天天向上")
f
}
//使用匿名函数调用了fun函数,因为fun函数有返回值,所以用一个变量接收,刚刚好这个变量又是函数,可以调用
val show: String => Int = fun((s: String) => s.toInt)
//调用show函数
println(show("1000"))
4.2.2 只有返回值是函数
1.返回值是啥类型,就要在内部创建一个改样类型的函数。
2.返回值直接写内部创建函数的函数名
3.调用函数得到也是一个函数
4.对于这种的可以直接简化
5.好处:传值可以分开,当函数原本一次性传递多个参数的时候,现在改成分开传递参数的形式,增加了函数的灵活性和可复用性,scala的函数柯里化:函数的返回值依旧是一个函数,继续传参
//定义一个参数类型为String,返回值是参数列表是String->Int的函数
def fun1(str:String):String=>Int={
//因为这里的返回值是参数列表是String->Int的函数,需要在fun1里面创建一个这样的函数
def show1(s:String):Int={
str.toInt+s.toInt
}
//需要返回一个参数列表是String->Int的函数
show1
}
//上面函数的简写形式
def fun2(str: String)(str1: String): Int = {
str.toInt+str1.toInt
}
//调用fun2函数
println(fun2("1000")("1000"))
//调用fun1函数
val get: String => Int = fun1("1000")//这是函数
val i: Int = get("1000")
println(i)
//简化写法
val i1: Int = fun1("1000")("1000")
println(i1)
6.偏函数:中间由scala产生的函数,称之为偏函数
def fun3(str1:String,str2:String):Int={
str1.toInt+str2.toInt
}
//偏函数
val show3: String => Int = fun3("10", _)
println(show3("10"))
println(show3("20"))
println(show3("30"))