#day1# scala基础
*.名词:
*表达式:可计算的语句
*常量:val,不能被重新赋值
*变量:var,能被重新赋值
*代码块
*函数:带有参数的表达式
*方法:由def定义,后面跟一个方法名、参数列表、返回类型和方法体
*类:class定义,跟类名和构造参数
*样例类:case class 跟类名和参数,默认情况下,样例类一般用于不可变对象,并且可作值比较,样例类可以不用new关键字来实例化
*对象:对象是他们自己定义的单实例,可以把它看做是它自己的类的单例。可以使用object关键字定义对象
*特质:trait,包含某些字段和方法的类型,可以组合多个特质。特质可以有默认的实现,可以使用extends关键字来继承特质,可以使用override关键字来覆盖默认的实现。
*主方法:程序的入口
1.scala解释器
scala解释器读到一个表达式,对它进行求值,将它打印出来,接着再继续读下一个表达式,这个过程被称作读取-求值-打印-循环,即REPL。
从技术上讲,scala程序并不是一个解释器,实际发生的是,你输入的内容被快速地编译成字节码,然后这段字节码交由Java虚拟机执行,正因如此,大多数Scala程序员更倾向于将它称做为“REPL”。
常用命令:
:help
:quit / :q
:load filename
:paste ctrl+d结束
2.声明值和变量
val:常量
var:变量
3.常用类型
scala并不刻意区分基本类型和引用类型,你可以对数字执行方法,例如:
*1.toString() //产出字符串“1”
*1.to(10) //产出Range(1,2,3,4,5,6,7,8,9,10)
在 scala中,用方法而不是强制类型转换,来做数值之间的转换,例如:
*99.44.toInt 得到99
4.算术和操作符重载
scala并没有提供++和–操作符,需要使用 += 1,或者 -= 1 ,例如:
*counter += 1 //将counter递增;
5.调用函数和方法
scala中使用数学函数更为简单,你不需要从某个类调用他的静态方法。 例如:
*sqrt(2) //1.4142135623730951
scala没有静态方法,不过他有一个类似的特性,叫做单例对象,通常,一个类对应有一个伴生对象,其方法就跟Java中的静态方法一样
6.apply方法
7.scaladoc
8.类的定义
class 类名[([参数列表])] [{}]
*class A;
*class B{}
*class User (name:String,age:Int){}
构建实例对象
*new A()
*new B()
*new User(“tom”,“12”)
构造器
主构造器:与类的定义交织在一起
构造器是特殊的方法
辅助构造器:def this(){
//第一行代码必须调用主构造器或者是其他辅助构造器
} 可以无参
例如:
class User (name:String,age:Int){
//无参辅助构造器
def this(){
//调用主构造器
this(“孩子”,1);
}
//三参辅助构造器
def this(name:String,age:Int,passwd:String){
//调用主构造器
this(“父母”,30);
//调用其他的辅助构造器
this()
}
}
}
new User()
new User(“tom”,2)
new User(“kevin”,21,“13155”)
Class Student(val/var age:Int){},花括号可以省略
如果在age前面加了val,会自动在当前类中提供age的get()方法
如果在age前面加了var,会自动在当前类中提供age的get()和set()方法,get() -> age ; set -> age_=
Class Student(【private将方法私有化】val/var age:Int){}
java中 public 类名{}
scala中除了属性,除了方法,都是主构造器的
定义类时在参数列表里加上val,会自动提高当前参数的get方法,加上var时会自动提供get以及set方法。
样例类
样例类小括号不能少
case class Person([val]隐含的val,也可以加var age:Int){}
样例类会提供22种方法
9.伴生类/对象的声明
Object关键字声明
* Object Stu {} 单例对象
//程序 入口
def main(args:Array[String]:Unit={
...
def test1(){
}
}
对象调用方法:Stu.test1
**定义在类中的一般为非静态方法,定义在对象中的一般为静态方法。
伴生类/对象
Class User{}
Object User{}
静态的写在对象中,非静态的写在类中
vi Student.scala
scalac Student.scala
javap Student
10.特质 trait
格式: trait 特质名 extends 类/特质 with 特质1 {}
总结:
1.可以包含具体方法/属性
2.可以包含抽象方法/属性
3.特质 可以 混入 类/对象/特质/实例(对象)
trait Logger{
// 具体方法
def log(msg:String)={...}
def error(msg:String)={...}
def exception(msg:String)={...}
// 抽象方法,没有方法体
def test(msg:String):Unit
}
Class Student() extends Logger{}
val stu = new Student() with Logger();同时拥有类和特质中的方法
11.类型声明(给Int起别名叫A)
type A=Int
用处:当类型比较复杂时,当类型冲突时
java.util.hashMap
scala.collection.hashmap
解决类型冲突
type JavaHashMap = java.util.hashMap
type ScalaHashMap = scala.collection.hashmap
#day2#
函数式编程
1.高阶函数
2.支持闭包
3.类型推断
4.无副作用,无IO操作,不改变状态
5.引用透明 同一函数,传递相同参数,必然返回同一个值
1.方法 def
1.1.格式
[修饰符] def methodName
1.2.方法的返回类型是Unit时,称之为过程
eg:
def test1(a:Int):Unit={}
-----》可以变成如下写法:
def test1(a:Int){}
1.3.当方法为非递归方法时,可以将返回类型省略
eg:
def test(a:Int)={
a
}
递归方法不可以将返回类型省略
eg:
def fac(a:Int):Int={
a*fac(a-1)
}
1.4.方法调用 方法名(args)
1.对于无参数的方法,方法调用有两种: 方法名()或者 方法名
2.方法调用时,可以通过形参进行无顺序传递。
eg:def info(a:Int,b:Int,c:Int)= {
a+b+c
}
方法调用:
info(1,2,3)
info(a=1,b=2,c=3)
注意:当使用形参传递参数时,如果有未指明参数名的必须与对应位置相匹配,不可以随意放置。
1.5.可变参列表
1.只能位于参数列表最后一个
2.表示形式: 类型*
3.可变参本质上是一个集合
def test(a:Int,b:Int,c:Any*)={
println(c)
}
2.数据类型
数据类型
8种基本类型+Unit
Unit <===> ()
类层级结构:
Any(顶级父类,最顶级类)
AnyVal AnyRef(相当于Java中的Object)
8基本+Unit 引用类型
Nothing(所有类的子类,最底层类)
AnyVal包含:Byte Int Short Long Char Boolean Float Double + Unit
(实际Scala中是没有基本数据类型的)
AnyRef包含:String(java.lang) 集合类 数组 自定义数据类型 ...
3.类 class
3.1 格式:
class 类名 private[package] (主构造器参数列表) extends 类/特质 with 特质1 with 特质2{}
eg: class Student(name:String,age:Int) extends Father with T1 with T2{
//属性
//方法
//主构造器中的代码
println("…")
def this()={
//…
}
}
3.2 构造器
主构造器:与类的定义交织在一起
辅助构造器 :
1.通过方法名this重载构造器
2.辅助构造器的第一行代码必须是调用主构造器或者调用其他已经定义好的辅助构造器
3.3 主构造器参数列表
形式:
1.参数名:类型
2.var 参数名:类型
3.val 参数名:类型
4.private val/var 参数名:类型
5.@BeanProperty val/var 参数名:类型
day2 #2
1.标识符
大体上与Java一致。
特殊点:
1.Scala标识符中不允许出现$
2.反引号`` 可以将关键字等一些特殊字符使用反引号引起来,这样就变成了一个合法的标识符。
eg:return
class
val there is
=“jthbh”
2.关键字
Scala中的关键字基本上与Java一致。但存在个别Java关键字在Scala中不是关键字的特例。
eg: break
第一天学习过程中认识到的关键字:
class val var object def trait type return this super private protected
Byte Short Int Long Char Float Double Boolean Unit Array extends with abstract
3.操作符
算数运算符 逻辑运算符 位运算符 …等 与Java使用一致。
需要注意的是:
1.scala中本质上没有操作符,都是方法的调用。
2. Scala中 == 与 equals 一致,都是比较值
eq与ne比较的是地址。
stu1.eq(stu2)
1 + 2
1.+(2)
1 to 10
1.to(10)
3.在Scala中,运算符即是方法。 任何具有单个参数的方法都可以用作 中缀运算符。
例如,可以使用点号调用 +:
10.+(1)
而中缀运算符则更易读:
10 + 1
4.注释
当行注释://
多行注释:/* /
文档注释:/* */
5.控制结构(重点讲解)
5.1 块语句/表达式
val info={
val b=0;
val a=9;
val sum=a+b;
println(sum);
}
5.2 if表达式
val info=if(3>5){
1.3
}else{
0
}
val info=if(3<5){0.8}
5.3 输入输出
Console.println
print
printf
scala.io.StdIn.readLine
readInt
(注意:一个scala源码中默认导入3个包)
import java.lang
import scala._
import scala.Predef._
5.4 循环
while do for
for推导
1.格式: for(发生器){循环体}
eg:
for(elem <- 1 to 10){…}
发生器的格式: i <- e
i 为变量
e 为需要遍历的元素(数组,列,表达式,数值范围等)
注意 for 表达式并不局限于使用列表。任何数据类型只要支持 withFilter,map,和 flatMap 操作(不同数据类型可能支持不同的操作)都可以用来做for推导。
2.if守卫
格式:for(发生器 if守卫){循环体}
eg:
for(elem <- 1 to 10 if i%20 if i%30){…}
for(elem <- 1 to 10 if i%20&&i%30){…}
3.for嵌套
格式:for(发生器1;发生器2;…){…}
eg:
for(i <- 1 to 9;j <- 1 to 9){…}
4.for嵌套+if守卫
格式:for(发生器1 if守卫;发生器2;… if守卫 if守卫 if守卫){…}
eg:
for(i <- 1 to 10;j<- 1 to 9; if i%20 if j%30){…}
for(i <- 1 to 10 if i%20;j<- 1 to 9 if j%30){…}
5.for yield 返回新的集合
格式:for(发生器) yield {循环体}
eg:
val newCollection=for(i < 1 to 10) yield {i+2}
注意: 除了for yield之外的其他for循环都是一个过程,即没有返回值。
5.5 函数: 现阶段不具体区分方法和函数,因此与day1方法讲解的一致。
5.6 异常
Scala中的异常有三种处理办法:
1. try catch finally
格式:
try{}catch{case e:Exception=> }
try{}catch{case e:Exception=>}finally{}
try{}finally{}
注意:
1.支持上边这三种格式,注意最后一种在Java中是不支持的。
2.catch代码块中没有了所谓了参数列表。
3.catch代码块中使用case语句去匹配异常信息。
eg:
try{
//可能会发生异常的代码
}catch{
// e,x 只是一个变量,被val修饰的变量。因此,可以自己设置成符合Scala标识符规范的变量名即可。
case e:IOException =>
println(e.getMessage)
case x:NullPointerException =>
//…
//…
}
2. Option None Some (后期文章中分享)
3. Try Success Failure (后期文章中分享)
5.7 其他语句
scala不推荐使用return语句。
break/continue在C++中非常常见的控制结构语句,但在Scala中是不必要的,可以使用布尔值类型的量通过IF语句进行控制
注意:scala中没有break和contine关键字,如果想要结束多层循环,可以使用如下代码:
import scala.util.control.Breaks._
break例子:
breakable{
for (i<- 1 to 10){
if (i5)
break
}
}
continue例子:
for(i<-0 until 10){
breakable{
if(i3||i==6) {
break
}
println(i)
}
}
6.包与引用:import语句用于导入其他包中的成员(类,特质,函数等)
6.1包对象
每个包都可以有一个包对象,需要在父包中定义它,且名称与子包一样。
格式:
package com.briup.test
package object 包名{
val defaultName=“tom”;
}
在其他地方,这个常量可以用com.briup.test.包名.defaultName访问到。
包对象被编译成带有静态方法和字段的JVM类,名为包名.class,位于相应的包下。
对源文件使用相同的命名规则是好习惯,可以把包对象放到文件com/briup/test/包名/包名.scala。这样一来,任何想要对包增加函数或变量的话,都可以很容易地找到对应的包对象。
6.2默认导包
import java.lang._
import scala._
import scala.Predef._
注意:区分先后顺序
6.3包引入重命名
//全部导入
import scala.collection.mutable._
//重命名
import java.util.{ HashMap => JavaHashMap }
//将HashMap之外全部导入
import java.util.{ HashMap => ,}
6.4包的作用范围
与变量的作用范围一致,不可以在引用范围之外使用该包内的类,对象。
6.5如果存在命名冲突并且你需要从项目的根目录导入,请在包名称前加上 root
package accounts
import root.users._
6.6Scala 不同于 Java 的一点是 Scala 可以在任何地方使用导入
def sqrtplus1(x: Int) = {
import scala.math.sqrt
sqrt(x) + 1.0
}
###第七章、集合
Seq trait用于表示序列。所谓序列,指的是一类具有一定长度的可迭代访问
的对象,其中每个元素均带有一个从0开始计数的固定索引位置。Seq是一个
有先后次序的值得序列,比如数组或列表。IndexSeq允许我们通过整型的下
标快速访问任意元素,如ArrayBuffer是带下标的。
Set是一组没有先后次序的值,在SortedSet中,元素以某种排过序的顺序被
访问。
Map是一组(K,V)对偶,SortedMap按照键的排序访问。
每个Scala集合特质或类,都有一个带有apply方法的伴生对象,这个apply方
法可以用来构建该集合中的实例。
List:列表
::
头部、尾部
遍历列表:迭代遍历,for循环遍历,自定递归方法遍历
set集
不重复元素的集合,以哈希集实现
new HashSet
HashSet.apply
HashSet.empty
位集
存放非负整数
操作符
特质:类似于接口,但是比接口强大
特质中可以有方法的具体实现
继承一个类或者特质,用extends或者with
如果一个类继承多个特质,第一个特质用extends,其他的特质用with
如果一个类继承了一个类(或者抽象类)和一个特质,继承类(或者抽象类)使用extends,继承特质使用with
访问权限
scala中也有四种访问权限
public是默认的访问权限,没有关键字
protected 访问权限只能子类访问,同包访问不了
private 私有访问权限,只能当前类访问
包访问权限需要采用特殊的语法规则: private[包名]
动态绑定机制:成员方法在执行的过程中,JVM会将方法和调用对象的实际内存进行绑定,属性没有动态绑定机制,属性在哪里声明在哪里使用
scala中属性也可以重写,因为属性可以抽象
属性只有声明,而没有初始化,那么就是抽象属性
抽象属性在编译为class文件时,不产生属性,但是产生抽象getter方法
属性可以被覆盖(重写),但是不能重写父类var声明的变量
父类构造方法:
如果父类的主构造方法有参数,那么构建对象时必须显示的传递参数
可以在继承的父类后面增加小括号,传递参数,等同于调用父类构造方法