Scala的变量与类型

目录

一、变量

1.1变量推断

1.2多变量定义

1.3var和val的区别

1.3.1是否可变

1.3.2延迟加载

1.3.3使用val 还是var?

二、类型

         2.1类型层级关系

2.2值类型AnyVal

2.3非值类型

2.3.1字符串类型

2.3.3符号类型

2.3.4Option类型

2.4其他类型

三、类型转换

3.1 自动类型转换

3.2强制类型转换

3.3数值类型和字符串类型的转换


一、变量

变量声明一定要初始化  
val 修饰的变量,相当于 Java fifinal 修饰的变量 ;
// 定义常量 s1 ,使用字符串 "1" 赋值,自动推断为 String 类型,值不可变
val s1 = "1"
// 定义常量 s2 ,手动指定类型为 String ,此时需要保证所赋值类型匹配
val s2 : String = "2"
// 使用 val 定义基本数据类型时,值不可变,可以使用 val 重新定义

1.1变量推断

含义:声明变量时,可以不指定变量类型,编译器会根据赋值内容自动推断当前变量的类型。
// 定义变量a1,使用1赋值,自动推断为Int类型
var i1 = 1
print(i1.isInstanceOf[Int])
//类型确定后,就不能再赋值的类型
i1 = 1.1

1.2多变量定义

//Java中支持一行同时定义多个同类变量:
String a = "Hello", c = "hello";
int x = 5, y = 5;
//scala中的多个变量的初始化:
val (a, b, c) = (1, 2, "a")
// 定义变量a3,a4,同时赋值为10
var i3,i4 = 10;

1.3varval的区别

# val var 的区别
- 是否可变
- 是否可以有 lazy 修饰 : 延迟加载

1.3.1是否可变

         使用val声明一个常量或值: val 修饰的变量是不可变的,注意不可变的是引用,而不是内容 ==val 修饰的变量在编译后,等同于加上fifinal==
        使用var 声明一个变量: var 修饰的变量,内容和引用都可变
(扩展一下什么是值类型,什么是引用类型,可以使用数组举例,引用不可变,变的是内容。)
可变和不可变?
可变和不可变,指的是变量本身存的内容,值类型变量存的是数据本身,而引用类型变量存的是数据的引用,
值类型和引用类型?
值类型与引用类型区别:
存储方式 :直接存储数据本身 vs 存储的是数据的引用,数据存储在数据堆中
内存分配 :分配在栈中 vs 分配在堆中
效率 :效率高,不需要地址转换 vs 效率较低,需要进行地址转换
内存回收  : 使用完后立即回收 vs 使用完后不立即回收,而是交给 GC 处理回收
//定义了一个数组,arr存储的是一个地址在栈区,Array(1, 2, 3, 4, 5) 才是真正存储数据的在堆区,
//arr的地址指向Array(1, 2, 3, 4, 5)这个数组
scala> val arr = Array(1,2,3,4,5) 
    arr: Array[Int] = Array(1, 2, 3, 4, 5) 

//改变arr地址的指向
scala> arr = Array(1,2,3)
    //错误,发现不能改,这就是因为arr是val定义的,不能改
    <console>:8: error: reassignment to val arr = Array(1,2,3) 

//修改arr指向的数组里面的值
scala> arr(0)=10 

//发现修改成功
//注意这个val不能改的是arr而arr存储的是指向那个数组的地址
//修改成功的是修改被指向的数组里面的值
//而不是修改arr存储的地址,所以成功
scala> arr 
    res1: Array[Int] = Array(10, 2, 3, 4, 5)

1.3.2延迟加载

        只有val 修饰的变量才能被 lazy 修饰 ,使用 lazy 定义变量后, == 只有在调用该变量时才会实例化这个变量的值 == ,类似方法,先声明,后调用。
scala> val a = 10 
a: Int = 10 

scala> lazy val b = 100 
b: Int = <lazy> 

scala> b 
res2: Int = 100 

scala> var c = 10 
c: Int = 10 

scala> lazy var d = 100 
<console>:1: error: lazy not allowed here. Only vals can be lazy lazy //懒加载var的错误
    var d = 100 
    ^ 

scala> def e = 1000 
e: Int 

scala> e 
res3: Int = 1000

注意:lazy的变量在定义是时候不会加载到内存,只有在使用这个变量的时候才会加载

1.3.3使用val 还是var?

# 官方推荐 val, 使用 val 的好处:
        - 更安全
        - 代码可读性更高
        - 资源回收更快,方法执行完, val 所定义的变量即回收

二、类型

        2.1类型层级关系

 # Any是所有类型的父类

        它定义了一些通用的方法如equals、hashCodetoStringAny有两个直接子类:AnyValAnyRef

# AnyVal 是所有值类型的父类
        有9 个预定义的非空的值类型分别是: Double Float Long Int Short Byte Char Unit Boolean 。Unit是不带任何意义的值类型,它仅有一个实例可以像这样声明: () 。所有的函数必须有返回,所以说有时候 Unit 也是有用的返回类型。
# AnyRef 是所有引用类型的父类
        AnyRef代表引用类型。所有非值类型都被定义为引用类型。在 Scala 中,每个用户自定义的类型都是 AnyRef 的子类型。如果Scala 被应用在 Java 的运行环境中, AnyRef 相当于 java.lang.Object
# Nothing 是所有类型的子类
        Nothing是所有类型的子类,也是 Null 的子类,他没有一个具体的实例对象,常见的应用如:抛出异常、程序exit,无限循环等,返回值为 Nothing 类型。
        Nothing没有对象,但是可以用来定义类型。例如,如果一个方法抛出异常,则异常的返回值类型就是 Nothing(虽然不会返回 )
        def get(index:Int):Int = {
                if(x < 0) throw new Exception(...) //返回值类型Nothing
                else ....
        }
# Null 是所有引用类型的子类
        Null只有一个实例对象 null ,主要用来和其他的 JVM 语言进行互操作,但是几乎不应该在 Scala 代码中使用。

 Scala Java有着相同的数据类型:

数据类
描述
Byte
8 位有符号补码整数。数值区间为 -128 127
Short
16 位有符号补码整数。数值区间为 -32768 32767
Int
32 位有符号补码整数。数值区间为 -2147483648 2147483647
Long
64 位有符号补码整数。数值区间为 -9223372036854775808 9223372036854775807
Float
32 , IEEE 754 标准的单精度浮点数
Double
64 IEEE 754 标准的双精度浮点数
Char
16 位无符号 Unicode 字符 , 区间值为 U+0000 U+FFFF
String
字符序列
Boolean
true false
Unit
表示无值,和其他语言中 void 等同。用作不返回任何结果的方法的结果类型。 Unit 只有一个实例
值,写成 ()
Null
null
Nothing
Nothing 类型在 Scala 的类层级的最低端;它是任何其他类型的子类型。
Any
Any 是所有其他类的超类
AnyRef
AnyRef 类是 Scala 里所有引用类 (reference class) 的基类

 Scala数据类型的位数,不受具体OS的影响,以保证Scala程序的可移植性。

2.2值类型AnyVal

        Scala和 Java 一样,有 8 种数值类型 Byte Char Short Int Long Float Double 和一个 Boolean 类型,和 Java不同的是 ,Scala 没有基本类型与包装类型之分,这些类型都是类,有自己的属性和方法。
        
// 相当于Java的包装类; 
1.toString() 
1.to(10)

常见的类型我就不一 一说了   转义字符跟其他的一样

Unit 类型
// Unit为空类型,相当于void,使用()进行初始化
var u = ()

2.3非值类型

AnyRef (引用类型)包括 List String 以及自定义类等。

2.3.1字符串类型

上图没有,但也是属于这里,这个比较特殊,属于这里,但使用的各性质跟数值类型一样

String 类型是有双引号包含的一个或者多个字符组成,语法和字符类型基本一致。
val hello = "hello" 
val escapes = "\\\"\'"
Scala 中引入的 三引号 作为字符串的开始和结束符,内部的原始字符串可以包含换行、引号和特殊字符
println("""welcome to
           "1000phone".""") 
//为了解决每行的空格,引入了stripMargin方法。使用方式是把管道符号(|)放在每行前面,然后对整个字符串 调用该方法。 
println("""|welcome to 
           |"1000phone".""".stripMargin)

2.3.3符号类型

Symbol类型也可以描述字符串,相比较于String类型,有两个比较明显的特点:节省内存和快速比较。

scala> val symbol1=Symbol("hello") 
symbol1: Symbol = 'hello 

scala> val symbol2='hello //等价于Symbol("hello") 
symbol2: Symbol = 'hello 

scala> symbol1==symbol2 
res16: Boolean = true 

scala> symbol1.name 
res20: String = hello
        标识符  是符号字面量( character literal )的写法,这里 < 标识符 > 可以是任何字母或数字的标识,但不能以数字开头,符号字面量被映射scala.Symbol 的实例。

2.3.4Option类型

Scala Option(选项)类型用来表示一个值是可选的(有值或无值) Option 有两个子类,分别是 Some None
Option[T] 是一个类型为 T 的可选值的容器:
  • 如果值存在, Option[T] 就是一个 Some[T]
  • 如果不存在, Option[T] 就是对象 None
scala> val name:Option[String]=Some("Jason") //Option[T],这里T是String,是泛型写法 
name: Option[String] = Some(Jason) 

scala> name.get 
res3: String = Jason 

scala> val age:Option[Int]=None 
age: Option[Int] = None 

scala> age.get //age为None,调用get方法报错 
java.util.NoSuchElementException: None.get 
    at scala.None$.get(Option.scala:347) 
    at scala.None$.get(Option.scala:345) 
    ... 32 elided 

scala> age.getOrElse(0) //防止age为None,指定默认值0 
res5: Int = 0
注意 :用户自行定义的类均为 AnyRef 类型。

2.4其他类型

Any
// Any可以接收任意的基本类型和引用类型 
var any: Any = null 
any = anyR //anyR:AnyRef 
any = anyV //anyR:AnyVal
AnyRef
// 可以使用AnyRef接收任意的引用类型 
var anyR: AnyRef = null
        在 Scala 中,字符串的类型实际上是 Java String ,它本身没有 String 类。 在 Scala 中, String 是一个不可变的 对象,所以该对象不可被修改。这就意味着你如果修改字符串就会产生一个新的字符串对象。
AnyVal
// 可以使用AnyVal接收任意的基本类型
var anyV: AnyVal = u // Unit 
anyV = b1 // Boolean 
anyV = b // Byte 
anyV = s // Short 
anyV = c // Char 
anyV = i // Int 
anyV = f // Float 
anyV = l // Int 
anyV = d // Double 
anyV = str // String
Null
// null值只能被推断为Null类型,null代表空值,可以被赋值给任何 
AnyRef类型的常量或变量 var n = null
Nothing
/*Nothing类型在Scala的类层级的最底端,它是任何其他类型的子类型。 当一个函数,我们确定没有正常
的返回值,可以用Nothing 来指定返回类型,这样有一个好处,就是我们可以把返回 的值(异常)赋给其
它的函数或者变量(兼容性)。前面None类型就应用了该特点:*/
 case object None extends Option[Nothing] { 
    def isEmpty = true 
    def get = throw new NoSuchElementException("None.get") //get方法返回Nothing类型 
 }

三、类型转换

3.1 自动类型转换

val x: Long = 987654321 
val y: Float = x // 9.8765434E8 (note that some precision is lost in this case) 

val face: Char = '☺' 
val number: Int = face // 9786

 Double转为Int时,错误如下:

scala> val i:Int=10d 
<console>:11: error: type mismatch; 
    found : Double(10.0) 
    required: Int 
        val i:Int=10d

 Char转整型时:

scala> val a:Byte='a' //英文1个字节,正确 
a: Byte = 97 

scala> val a:Byte='我' //中文2个字节,所以报错 
<console>:11: error: type mismatch; 
    found : Char('我') 
    required: Byte 
        val a:Byte='我' 

scala> val a:Short='我' //正确 
a: Short = 25105 

scala> val a:Int='我' //正确 
a: Int = 25105 

scala> val a:Float='我' 
a: Float = 25105.0
小结:
低位数可以向高位数数转换。如 Byte->Short
字符可以转整形或浮点型,不同长度字符应使用不同位数的整型
整型可以转浮点型,允许精度丢失。如 Long->Float

 3.2强制类型转换

scala 中转换:
//toByte toChar toDouble toFloat toInt toLong 
//toShort toString 
scala> val a = 19.9 
a: Double = 19.9 

scala> val b = a.toInt 
b: Int = 19 

scala> val c=a.asInstanceOf[Int] //类似Java中的强制类型转换:(int)a 

c: Int = 19
Scala Java 类型检查和转换对比
Scala
Java
obj.isInstanceOf[C]
obj instanceof C
obj.asInstanceOf[C]
(C)obj
classOf[C]
C.class

3.3数值类型和字符串类型的转换

数值类型转字符串类型
val s1 = true+"" 
val s2 = 3.1415+"" 
val s3 = 100 +""
字符串类型转数值类型
val s4 = "3.14" 
s4.toDouble()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值