一、什么是scala
scala 是基于JVMde 编程语言。JAVA是运行在jvm上的编程语言,java 源代码通过jvm被编译成class 文件,然后在os上运行class 文件。scala是运行在jvm 上的编程语言,scala源代码通过jvm被编译成class文件,然后在os上运行class文件。
二语法:
1.声明值和变量
var a =12 // 定义变量 vary
val b = 23// 定义常量:value
2.有趣的语法特性
在scala的变量声明时,可以不指定类型,由解释器自己判断。
“superman ”*3 //表示字符串“ superman”反复输出3次 “superman ”*3 //实际上是字符串“ superman”调用方法*,传入的参数是3
3.函数:
函数在声明后,无论是否有“=”,都有返回值。当没有“=”的时候,表示返回值是Unit类型,Unit类型的值是()。当有“=”的时候,返回值是函数体中的最后一行的值。如果返回值类型强制指定为Unit类型,那么返回值必定是()。
4. 判断:
/** * 判断if */object Test21 extends App{ def judge(a:Int) :Int = { if(a > 0){ 1 //return相当于函数版的break语句 }else if(a < 0){ -1 }else{ 0 } } var c = judge(-3) println(c)}
5.循环
/** * while 和 for循环 */object Test22 extends App{ /*while循环*/// while(true){ // println("hello")// } /*for循环 scala中的for基本形态*/// for(int i = 0 ; i < 5 ; i++) //java的for循环// for( i : List) //增强for // println(1 to 10) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)// for(i <- 1 to 10 ){ //闭区间// println(i)// } // for(i <- 1 until 10 ){ //开区间// println(i)// } // for(i <- 1 until 10 reverse){ //倒序 不能使用 10 to 1// println(i)// } /*高级for循环*/ //守卫// for(i <- 1 to 10 reverse ; if i % 3 == 0){ // println(i)// } // for(i <- 1 to (10,3)){ //改变步长// println(i)// } // for(i <- 1 to 10 ; j <- 1 to 5){ //双重for循环// println(i + " - " + j)// } // //for的推导式// var c = for( i <- 1 to 10 )yield (i * 2)// println(c)
6.常用的数据结构
6.1数组
/** * 数组 */object Test31 extends App{ /*定长数组*/ //使用new定义数组// var arr1 = new Array[Int](5)// arr1(1) = 2 println(arr1)// for(i <- arr1){ // println(i)// } //使用Array类进行定义 var arr2 = Array(1,2,3,4,"hehe")// for( i <- arr2){ // println(i)// } // println(arr2.min)// println(arr2.max)// println(arr2.sum)// println(arr2.mkString("[",",","]")) //Arrays.toString(arr) [1,2,3] /*变长数组*/// var arrbuf1 = ArrayBuffer(1,2,3,4)// arrbuf1 += 5// arrbuf1 -= 3// arrbuf1 ++= Array(3,4,5)// arrbuf1 --= Array(3,4,5)// arrbuf1.toArray// println(arrbuf1.mkString(",")) // var arrB = arr2.toBuffer// arrB += 9// println(arrB.mkString(",")) //filter 和 map用法 var arr4 = Array(1,2,3,4,5) var arr5 = arr4.filter( _ % 2 == 0 ).map( _ * 2) println(arr5.mkString(","))}
6.2映射
** * 映射 */object Test32 extends App{ /*不可变的映射*/ //(zhangsan,18)键值对称作对偶 用()表示 var map1 = Map[String,Int](("zhangsan" , 18) ,( "lisi" , 19)) map1 += ("wangwu" -> 80)// map1("zhangsan") = 12 map1 += ("zhangsan" -> 20)// println(map1("zhangsan"))// for(i <- map1){ // println(i)// } // if(map1.contains("zhaoliu"))// println(map1("zhaoliu")) /*可变的映射*/// var mapB = scala.collection.mutable.Map[String,Int]("zhangsan"->20,"lisi"->12)// mapB("zhangsan") = 30// for(i <- mapB){ // println(i)// } /*与java的互操作*/// var list = new ArrayList[Int]// list.add(1)// list.add(2)// // for(i <- 0 to list.size() - 1 ){ // println(list.get(i))// } /*map其他遍历方式*/ // for((k,v) <- map1){ //方式一// println(k + "->" + v)// } //方式二 var set1 = map1.keys var set2 = map1.keySet for(i <- set1){ println(map1(i)) }// println(set2)
6.3元祖
/** * 元组 */object Test33 extends App{ //元组定义 //对偶(使用“()”表示)只是元组最简单的形式 使用()表示 var t = (1,2,3,4)// for(i <- t){ //元组不能使用for遍历// println(i)// } // println(t _3) //元组的下标从1开始// println(t _1) //元组的下标从1开始 var (first,second,third,forth) = t// var (first,second,third,_) = t// println(second) var s = "Hello World!"// println(s.partition(_.isUpper)) //拉链操作 var arr1 = Array(1,2,3,4,5,6) var arr2 = Array("a","b","c","d","e") var arr3 = arr1.zip(arr2) //// for(i <- arr3){ // println(i)// } println(arr3.mkString(",")) var map = arr3.toMap //map for(i <- map){ println(i) }
7.类
类的定义 : 使用class定义
类的字段:在类中使用var,val定义字段
类的方法:scala中,使用var定义字段默认提供setter和geter方法,对应的名称为value_= 和value.
/** * 类的基本内容 */class TestClass41{// @BeanProperty var monary = 100 var monary = 100 // def show { // println("hello")// }}object Test41 extends App{ var a = new TestClass41() //实例化一个类 a.monary = 200 println(a.monary)// println(a.show) //scala使用var定义字段 默认生成对应的setter和getter方法 对应的名称monary_= 和 monary // a setMonary 300// println(a getMonary) //使用val定义字段的时候 scala不在提供setter方法 //@BeanProperty和private不能同时共用 }/** * 类的基本内容2 */class TestClass42{ private var monary = 0 def setMonary(a:Int){ //自定义setter方法 if(a > 0) this.monary = a } def getMonary = { //自定义getter方法 this.monary } }object Test42 extends App{ var c = new TestClass42 c setMonary -1000 println(c getMonary) }
构造器:
/** * 类的构造器 *///class TestClass43(var name:String = "xxx" , var age:Int = 0) { //主构造器 带参数称为默认值// var name:String //需要初始化 var age:Int public TestClass43 {} //java的构造器写法// println("name=" + name)// println("age=" + age)// //}class TestClass43 { //辅助构造器 var name:String = "lisi" //需要初始化 var age:Int = 0 def this(name:String ){ this() //辅助构造器第一行要调用主构造器 this.name = name println("第一个辅助构造器") } def this(name:String ,age:Int){ this(name) //还可以调用其他辅助构造器 this.name = name this.age = age println("第二个辅助构造器") } println("name=" + name + " age=" + age) def show = { "name!=" + name + " age!=" + age }}object Test43 extends App{ var c = new TestClass43("wangwu",90)// println("name=" + c.name)// println("age=" + c.age) println(c.show) }
8.对象
定义:Object是一种类型,与class非常相似。Object可以提供java中的静态字段、静态方法的功能。伴生对象/** * 伴生对象 */class TestObject51 { private var value = 10 def display{ println(TestObject51.value) } def show(a:TestObject51){ //自定义getter方法 this.value = TestObject51.value }}/*伴生对象*/object TestObject51{ //对象使用object定义 //该对象作为同名类的伴生对象// private[this] var value = 10 private var value = 10 private def show { println("超人") }}object Test51 extends App{ // println(TestObject51.value) //不能访问对象中的私有字段// println(TestObject51.show) }apply 方法:f(arg1,arg2,**)是函数调用方法,用着非常好用,如果f是类的实例,相当于调用类的apply()方法。/** * apply方法 */object Test52 extends App{// var arr = new Array[Int](5) var arr = Array.apply(1,2,3,4) //构造数组使用的是apply方法 var map = Map.apply[String,Int]("zhangsan"->12) }
9.高阶函数
1.函数可以赋给变量值首先,在scala中,函数是一等公民2.匿名函数:函数的形式是(形参列表)=>返回值类型var ff = (s: string) => s.toUpperCaseprintln(ff)/** * 高阶函数 */object Test61 extends App{ //函数定义 def add(a:Int ,b:Int) = { a + b }// var c = add(1,2)// println(c) var func1 = add _ //把一个函数的实现传递给另外一个函数 // println(func1(1,2)) // var func2 = (x :Int) => x + 3 //传递一个匿名函数给给一个变量// var func3 = (x :Int) => {x + 3} //传递一个匿名函数给给一个变量// var func4 = (x :Int) => (x + 3) //传递一个匿名函数给给一个变量 // for(i <- arr) // Map[String,Int]("zhangsan" -> 12)// println(func2(3)) // def func5(a:Int ,f:(Int)=>(Int)) = { // f(a) + 1// }// println(func5(4,(x:Int) => {x + 2})) //传递一个匿名函数给该函数 //调用函数封装举例// def CPU(a:Int) = { // a * 8// }// def GPU(a:Int) = { // a + 9// }// def compute(men:Int,CPU:(Int)=>(Int),GPU:(Int)=>(Int)) = { // men + CPU(2) + GPU(2) // }// println(compute(4,CPU,GPU)) def func6(f:(Int)=>(Int)) = { f(1) }// println(func6(_ + 2)) //简写条件:1.只有一行代码 2.只有一个形参 3.把匿名函数作为形参// println(func6(_ + _)) //总结“_” :// 1.代表数组每一个元素// 2.指的是传递是确切的一个函数 而不是忘记给该函数传递参数// 3.元组的元素取值 //思考题// def func7 (x :Int ,y:Int) = { // (y : Int) => { // x + y// } + 2// }// println(func7(3,4)(2)) //一些有用的函数 map foreach reduceLeft // (1 to 9).map("*" * _).foreach(println _) var c = (1 to 3).reduceLeft(_ + _) //1 + 2 + 3 println(c) }
3. 函数作为形参(demo 同上)
对于只有一个参数的,可以只写函数体。
fun3(a=>a+2)
如果形参只有一个,可以在函数体中使用_代替。
fun3(_+2)
函数作为形参的终极版本。
4.把匿名函数放在函数体内
5.一些有用的高阶函数
10.继承:
抽象类
1.抽象类不一定有抽象字段,有抽象字段或者抽象方法的类一定是抽象类,只需要添加abstract关键字 2.有抽象字段一定是是抽象类(scala中字段定义时一定要初始化) 3.重写字段时实质就是在重写字段的setter/getter方法覆盖方法
非抽象类覆盖方法的时候,一定使用override。
覆盖字段
抽象字段一定要有类型描述。 覆盖的时候,一定使用override。
/** * 继承--抽象类 */abstract class Person { //抽象类不一定有抽象字段或者抽象方法 //有抽象字段或者抽象方法的类 一定是抽象类 var name:String val age:Int def story:String}//方式一//class Student extends Person{ //覆盖字段时实质上是覆盖了字段setter、getter方法// var name:String = "Jeckson" //var定义的字段只能使用var覆盖,并且var覆盖只能是为实现的字段 // val age:Int = 20 //使用val定义的字段只能使用val覆盖 def story = "dance" //// def story = "dance" //使用def定义的抽象方法可以使用def覆盖也可以使用val ,当def为无参时函数可以使用val//}//方式二//class Student (var name:String = "Jeckson" ,val age:Int = 20 ,val story:String = "dance") extends Person object Test71 extends App{// var c = new Student// println(c.name)// println(c.age)// println(c.story) var c = new Person { //方式三 匿名子类 var name:String = "Jeckson" //var定义的字段只能使用var覆盖,并且var覆盖只能是为实现的字段 val age:Int = 20 //使用val定义的字段只能使用val覆盖 def story = "dance" // }}
匿名子类重写超类
抽象字段和抽象方法
/** * 构造顺序 */class Person1 { val age:Int = 10 var arr:Array[Int] = new Array[Int](age) //调age字段的getter方法}//class student1 extends Person1{ // override lazy val age:Int = 18 //如果覆盖的父类不是抽象类 必须要写override//}class student1 extends { //解决办法③ override val age:Int = 18 //如果覆盖的父类不是抽象类 必须要写override} with Person1//特质/*trait student2 { var a:Int = 10 var b:Int}trait student3{ def show = "123"}class student4 extends student2 with student3{ var b:Int = 1}*/object Test72 extends App{ var c = new student1 println(c.age) println(c.arr.length) //输出18 0 解决办法:1.字段前面添加final 2.字段前面添加lazy 3.解决办法③ //原因:// a.主构造器和class类交织在一起// b.子类中使用了override覆盖超类中的字段,构造子类时超类的字段值会被覆盖// c.student1类作为student1的主构造器,调用了超类的Person1的主构造器// d.首先,构造器将age值设置为10// e.接着代码往下走,为了初始化arr数组,调用了age的getter方法// f.而age字段被重写了,也就是说getter方法被重写了// g.被重写的getter方法还没有被初始化,确切说就是字段age还是对象在被分配空间时所有整型字段的初始值// h.arr数组长度被设置为0// i.子类Student1类构造器执行,age被赋值为18}
10 .模式匹配
更好的switch case
object Test73 extends App{// var t = (1,2,3)// var (first,second,third) = t //模式匹配// println(first) var s = "++" var result = s match { case "a" => println("超人") case "*" => 1 case "牛人" => "superman" case _ if s.contains("=") => (x:Int) => {x + 1} case _ => 0 } println(result)}
仅此献给努力的你我。