scala知识点
1.从技术上讲,scala程序不是一个解释器,它只是快速的将输入的内容翻译成字节码,然后交由JVM执行。
2.scala有7种数值类型:Byte,Char,Short,Int,Long,Float和Double,以及一个Boolean。跟java不同的是,这些是类。
scala不刻意区分基本类型和引用类,scala中,不需要包装类型。在基本类型和包装类型之间的转换是scala编译器的工作。
3.操作符和java不同的是他们是类的方法。scala为提供++或--方法,而是改以+=,-=
4.不带参数的scala方法通常不适用圆括号。
5.apply方法是()操作符的重载形式。
6.标记为implicit的方法对应的是自动(隐式)转换。
7.在scala中,每个表达式都应该有某种值。if(x>1) 0 如果条件不满足,则返回的是().
scala引入了一个Unit类,写作().表示的是“无有用值”的占位符。
8.可以使用readLine从控制台读取一行输入。相对应的还有readInt,readDouble等
9.lazy值的初始化会被延迟,直至首次对它取值。lazy值也是有开销的,每次访问lazy值时,都会有一个方法被调用,该方法以线程安全的方式检查该值是否已被初始化。
10.scala的工作机制和java一样,但不同的是scala不需要声明函数或方法可能会抛出某种异常。
在函数声明可能抛出异常,这个是在编译器被检查的,scala不搞这样的
scala捕获异常的方式是采用模式匹配的方法。
try{
}
catch{
//与java一样,更通用的异常应该排在更具体的异常之后。
}
finally{
}
11.Array:定长数组。
new Array[类型](长度)
scala中的Array以Java数组方式实现。
ArrayBuffer:变长数组
new ArrayBuffer[类型]() //不需要指定长度
在ArrayBuffer的尾端添加或移除元素是一个高效的操作,但是在其他地方则会有更大开销(涉及到移动元素)
从一个Array(或ArrayBuffer)出发,以某种方式对它进行转换不会修改原始数组,而是产生一个全新的数组。
对Array类的操作method放在ArrayOps的相关条目下。在数组上应用这些操作之前,数组都会被转换成ArrayOps对象。
12.多维数组,和java一样,通过数组的数组来实现的。可以用ofDim方法
13.与Java的互操作:scala数组是用java数组实现的,可以在java和scala之间来回传递
可以引入scala.collection.JavaConversions里的隐式转换方法。这样就可以在代码中使用ArrayBuffer,在调用Java方法时,这些对象会被自动包装成Java列表。
14.映射/哈希表:
Map[key_Type,Vaue_Type]=Map(key->value) //不可变
HashMap[key_Type,Vaue_Type]=Map(key->value) //可变
15.元组:
不同类型的值的集合。元组的各组元从1开始,而不是从0开始。
16.类:
scala对每个字段都提供getter和setter方法。可以通过scalac编译类,然后用javap查看字节码 //jvm中不允许在方法名中出现=
如果字段是私有的,那么getter/setter方法也是私有的
如果字段是val,那么只有getter方法生成
如果不需要任何的getter或setter,可以将字段声明为private[this]
private为类私有,只有该类可以看到
private[this]为对象私有,只有该对象可以看到
统一访问原则:某个模块提供的所有服务都应该能通过统一的表示法访问到,至于是通过存储还是通过计算实现的,从访问方式上应无从获知。
17.构造函数:
主构造函数类名(parm1:Type,[val/var] parm2,private/public/protectd parm3:Type3):parm1为public,parm2为private;
parm1:对象私有字段。如果没有方法是用这个参数,则没有该字段
parm2:对象私有字段,公有的getter/setter方法
parm3:对象字段。自动生成getter/setter方法
主构造器的参数被编译成字段,其值被初始化成构造时传入的参数
主构造器会执行类定义中的所有语句
如果类名之后没有参数,则该类具备一个无参主构造器。这样一个构造器仅仅是简单的执行类体中的所有语句。
辅助构造函数this([参数]):
每一个辅助构造函数都必须以一个对先前已定义的其他辅助构造函数或主构造函数的调用开始
18.嵌套:在scala中几乎可以在任何语法结构中内嵌任何语法结构
19.单例
scala用object实现类似于java的static方法或static字段.//java的static:被其修饰的成员变量/方法独立于该类的任何对象,并且被类的所有实例共享。只要这个类被加载,就可以通过类名去进行访问
object的构造函数在该object第一次被调用时执行。如果一个object从未被调用,那么其构造函数也不会执行
object本质上可以拥有类的所有特性,可扩展其他类或特质。但不能提供构造函数
使用场景:
作为存放工具函数或常量的地方
高效的共享单个不可变实例
单例模式
伴生对象
类名和object同名
类和其伴生对象可以相互访问私有特性,但必须在同一个源文件中
类的伴生对象可以被访问,但并不在作用域中。Account类可以访问lastNumber,但只能通过Account.newUniqueNumber来访问(通过伴生的object访问)
class Account{ //伴生类
val id=Account.newUniqueNumber
private varbalance=0.0
def deposit(amount:Double)={balance+=amount}
}
object Account{伴生object
private var lastNumber=0
private def newUniqueNumber={lastNumber+=1;lastNumber}
def apply=new Account() //一般返回伴生类的对象
}
对象的apply方法返回的是伴生类的对象
20.源文件的目录和包之间没有强制的关联关系
scala中包名是相对的,建议避免使用scala,java,com.org等名称来命名嵌套的包
包可以包含类,对象和特质,但不能包含函数或变量定义
每个包都可以有一个包对象,需要在父包中定义,且名称与子包一样。在慕后,包对象被编译成带有静态方法和字段的JVM类名为package.class.位于
import 包名(类名=>重命名,类名=>_) //引入的类可以重命名,第二个则是表示隐藏某个成员
scala包默认被引入。
21.类型检查和转换
isInstanceOf方法用于测试某个对象是否属于某个给定的类。
asInstanceOf方法将引用转换为子类的引用。
classOf:
只有主构造函数可以调用超类的构造函数。主构造函数是和类定义交织在一起的,调用超类构造函数的方式也同样交织在一起.scala类也可以扩展java类,它的主构造函数必须调用java超类的某一个构造函数
class Employee(name:String,age:Int,val salary:Double) extends Person(name,age)
22.重写字段
def只能重写另一个def
val只能重写另一个val或不带参数的def
var只能重写另一个抽象的var
23.抽象类
使用abstract关键字来标记不能被实例化的类,不需要对抽象方法使用abstract关键字,只要省去方法体;
在子类中重写超类的抽象方法时,不需要使用override关键字。
抽象字段是一个没有初始值的字段,带有抽象的getter/setter方法
具体的子类必须提供具体的字段
23.对象的相等性
AnyRef的equals方法调用eq.判断值是否相等。建议考虑实现equals方法,以提供一个自然的的判断
eq方法用于测试引用的相等性。null eq null返回true
==用来代表equals方法,用于测试值的相等性。null == null返回true
24.文件操作:
读取文件:scala.io.Source。用完需要close
写入文件:scala没有内建的对写入文件的支持。要写入文本文件,可使用java.io.PrintWriter
25.序列化:
java中用序列化来将对象传输到其他虚拟机或临时存储。
public class Person implements java.io.Serializable{private static final long serialVersionUID=42L;}
scala:
@SerialVersionUID(42L) class Person extends Serializable
Serializable特质定义在scala包,不需要显示引入。如果可以接受缺省的ID,也可以省略@SerialVersionUID(42L)注解
scala集合类都是可序列化的
26.进程控制
scala.sys.process包提供了用于与shell程序交互的工具。
27.正则表达式
scala.util.matching.Regex类用于处理正则
首先第一步需要构造一个Regex对象。
如果正则包含反斜杠或引号的话,最好使用原始字符串语法"""..."""(三引号)
28.特质
scala不允许从多个超类继承,但可以实现多个特质。
特质可以同时拥有抽象方法和具体方法
trait 名称{
method1 //特质中未被实现的方法默认就是抽象方法,子类在重写特质的抽象方法时不需要给出override关键字
method2={} //具体实现的方法,影响是当特质改变时,下游的类都必须重新编译
}
class extends 超类 with 特质1 with 特质2...
new 类 with 特质 //将该特质的方法加入到类中
在特质中重写抽象方法:
trait 子特质 extends 父特质{abstract override def 方法}
特质中的具体字段:
特质中的字段可以是具体的,也可以是抽象的
混入该特质的类自动获取一个字段.对于特质中的每一个具体字段,使用该特质的类都会获得一个字段与之对应。这些字段不是被继承,而是被简单的加到了子类当中。
特质中的抽象字段:
跟具体字段类似,不过不同的是需要给出具体的值。
特质的构造顺序:
1.首先调用超类的构造函数
2.特质构造函数在超类构造函数之后,类构造函数之前执行
3.特质由左到由北构造
4.每个特质当中,父特质先被构造
5.如果多个特质公有一个父特质,而那个父特质已经被构造,则不会被再次构造。
6.所有特质构造完毕,子类构造。
构造函数的顺序是类的线性化的反向:
如果c extends c1 with c2 with ...cn,则line(c)=c>>line(cn)>>...line(c2)>>line(c1) //>>表示串联并去掉重复项,右侧胜出。
幕后流程:
scala需要将特质翻译成JVM的类和接口
只有抽象方法的特质被简单的变成一个Java接口
如果特质有具体的方法,scala会创建出一个伴生类,该伴生类用static方法存放特质的方法。这些伴生类不会有任何字段。
特质中的字段对应到接口中的抽象的getter/setter方法,初始化发生在伴生类的一个初始化方法内。当某个类实现该特质时,字段被自动加入。
如果特质扩展自某个超类,则半生类并不继承这个超类,该超类会被任何实现该特质的类继承。
29.后置操作符的有限性低于中置操作符
提取器:一个带有unapply方法的对象
unapply方法接受一个对象,然后从中提取值-通常这些值就是当初用来构造该对象的值
unapply方法返回的是一个option。它包含一个元素,每个匹配到的变量各有一个值与之对应。
每一个样例类都自主具备apply和unapply方法

浙公网安备 33010602011771号