Scala变量
- Scala变量的注意事项
变量定义: var/val 变量名[:变量类型] =变量值
变量声明是需要初始值
var/val区别:
val 修饰的变量值是不可变的
var修饰的变量值可变
为什么有val/var类型之分?
(1)在实际编程中,我们最多的需求是在创建一个对象后,读取/修改这个对象的属性,而不是改变这个对象的本身。
(2)val没有线程安全问题,因此效率高,Scala的设计者使用推荐使用。
(3)val修饰的变量在编译后,等同于加上final
val dog = new Dog
//dog = new Dog // 报Reassignment to val,即不能给val修饰的重新赋值
dog.age = 20 //ok
//dog.name = "哮天犬"//又报错
class Dog{
var age:Int = 0
val name:String = "旺财"
}
Scala数据类型
Scala中数据类型都是对象,因此他的一个实例,可以用很多方法
Scala数据类型分为两大类AnyVal(值类型)和AnyRef(引用类型)。
Null类型是Scala的特别类型,他只有一个值null,他是bottom class,是所有AnyRef的子类
Nothing类型也是ottom class,他是所有类的子类,在开发中可以将Nothing类型的值返回给任意变量或者函数,这里抛异常使用比较多。
Scala数据类型列表
函数式编程
函数:
函数式编程:函数式编程把函数当成一等公民,充分利用函数,支持函数的多种使用方式。
在Scala中,函数是一等公民,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量。
- 惰性函数
惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们,这带来了一些好处。首先,您可以将耗时的计算推迟到绝对需要的时候。其次,您可以创造无限个集合,只要它们继续收到请求,就会继续提供元素。函数的惰性使用让您能够得到更高效的代码。Java 并没有为惰性提供原生支持,Scala提供了。
- lazy 不能修饰 var 类型的变量
- 不但是 在调用函数时,加了 lazy ,会导致函数的执行被推迟,我们在声明一个变量时,如果给声明了 lazy ,那么变量值得分配也会推迟。 比如 lazy val i = 10
lazy val res = sum(10, 20)
println("-----------------")
println("res=" + res) //在要使用res 前,才执行
}
def sum(n1: Int, n2: Int): Int = {
println("sum() 执行了..")
return n1 + n2
}
scala中"_"(下划线)的用法
1、方法转函数
def main(args: Array[String]): Unit = {
val fun=fbn _
fun(5)
}
//斐波那契数列
def fbn(n:Int):Int={
if (n==1||n==2){
1
}else{
fbn(n-1)+fbn(n-2)
}
}
2、作为函数的参数
//例如我们要在一个Array a中筛出偶数,并乘以2,可以用以下办法:
a.filter(_%2==0).map(2*_)。
//对于二元函数,参考如下
scala> List(10, 5, 8, 1, 7).sortWith(_ < _)
res0: List[Int] = List(1, 5, 7, 8, 10)
3、在元组中,可以用_1,_2,_3访问成员
4、某一类型的默认值
class Dog{
var a = _ //error
var b: Int = _ // right 只有用var修饰的,且指定了类型的才可以
val c:Int=_//error
val d =_//error
}
5、作为通配符
相当于Java中的*
6、模式匹配
val value="a"
val result= value match{
case "a" => 1
case "b" => 2
case _ =>"result"
}
println(result)
//这里的_相当于other的意思
面向对象
- 构造器
Scala构造器有两大类:主构造器和辅助构造器,其中辅助构造器可以有多个,编译器根据不同参数来区分。
class Person() {
var name: String = _
var age: Int = _
def this(name : String) {
//辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑
//而且需要放在辅助构造器的第一行[这点和java一样,java中一个构造器要调用同类的其它构造器,也需要放在第一行]
this() //直接调用主构造器
this.name = name
}
def this(name : String, age : Int) {
this() //直接调用主构造器
this.name = name
this.age = age
}
def this(age : Int) {
this("匿名") //简介调用主构造器,因为 def this(name : String) 中调用了主构造器!
this.age = age
}
override def toString: String = {
"name"+name+"=========="+"age"+age
}
}
- scala的bean属性
隐式转换和隐式参数
- 隐式函数
隐式转换函数是以implicit关键字声明的带有单个参数的函数。这种函数将会自动应用,将值从一种类型转换为另一种类型
//编写一个隐式函数 double =>int
implicit def f1(d:Double):Int={ //底层生成函数 f1$1
d.toInt
}
val x:Int=3.5 // f1$1(3.5)
println(x)
注意事项:
隐式转换函数的函数名可以是任意的,隐式转换与函数名称无关,只与函数签名(函数参数类型和返回值类型)有关。
隐式函数可以有多个(即:隐式函数列表),但是需要保证在当前环境下,只有一个隐式函数能被识别
- 隐式转换丰富类库
使用隐式转换方法动态的给MySQL类增加delete方法
object Impl {
//编写一个隐式函数,丰富MySQL功能
implicit def addDelete(mysql:MySQL):DB={
new DB
}
def main(args: Array[String]): Unit = {
val mySQL = new MySQL
mySQL.insert()
mySQL.delete() //编译器:addDelete$1(mysql).delete
}
}
class MySQL{
def insert(): Unit = {
println("insert")
}
}
class DB {
def delete(): Unit = {
println("delete")
}
}
- 隐式值
隐式值也叫隐式变量,将某个形参变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺省参数,可以作用在多个函数上
implicit val str1: String = "jack"
def hello(implicit name: String): Unit = {
println(name + " hello")
}
hello
在程序中同时存在隐式值,默认值,传值时,编译器的优先级为 传值 >隐式值>默认值,在隐式匹配时,不能有二义性,如果三个都没有,就会报错
- 隐式类