开发者学堂课程【Scala 核心编程-基础:】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8891
Scala 数据类型的一览图
目录
一、Scala 变量使用说明
上一节学习了 Scala 变量的使用及一些注意事项,继续学习注意事项:
1、var 修饰的对象引用可以改变,val 修饰的则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等) [分析 val 好处]
class Dog {
var age=100
}
2、变量声明时,需要初始值。
例:打开 VarDemo03.scala 编辑
package com.atguigu.chapter01.vars
object VarDemo03 {
var name = "hello"
val age = 100
def main(args: Array[String]): Unit = {
println("ok" )
var num1
}
}
变量声明时需要进行初始化,比如定义一个变量,var num1,这时必须给它一个初始值。在 Java 属性里,不给初始值就会给默认值。这里需要明确指定一个值,这个值也可以是默认值,必须要写。不能在 num 后面什么都不写。
二、程序中+号的使用
1、当左右两边都是数值型时,则做加法运算
2、当左右两边有一方为字符串,则做拼接运算
和 Java 程序中+号的使用是一样的。
三、Scala 数据类型介绍
虽然 Scala 与 Java 都是基于 JVM 的,但它们的数据类型变化非常大。
1、Scala 与Java有着相同的数据类型。在 Scala 中数据类型都是对象,也就是说 scala 没有 Java 中的原生类型
2、Scala 数据类型分为两大类 AnyVal(子类型) 和 AnyRef(引用类型),注意: 不管是 AnyVal 还是 AnyRef 都是对象。[案例演示 Int , Char]
3、相对于 java 的类型系统,scala 要复杂些!也正是这复杂多变的类型系统才让面向对象编程和函数式编程完美的融合在了一起。
4、案例
(1)Scala 与 Java 也有不同的数据类型。Scala 中的整型、浮点型、布尔值等等都是对象。
新建一个包,打开Java0705Scala,在scal文件目录上右击选择菜单 New,再选择 Package,命名为com.atguigu.chapter02,看到 com.atguigu 文件下有两个包,一个是 chapter01,一个是 chapter02。
在 chapter02文件包上右击选择 New,再选择 package,命名为 datatype,看到 chapter02.datatype 的包。再新建一个类,Name 为 TypeDemo01,Kind 为 Objiect。
① 思考:数据类型都是对象怎么理解?
编辑程序段:
package com.atguigu.chapter02.datatype
object TypeDemo01 {
def main(args: Array[String]): Unit= {
var num1: Int= 10
//因为 Int 是一个类,因此他的一个实例,就是可以使用很多方法
//在 scala 中,如果一个方法,没有形参,则可以省略()
println(numl.toDouble+"\t"+num1.toString )
sayHi
sayHi()
}
def sayHi(): Unit= {
println("say hi")
}
}
这里的 Int 首字母 I 大写。是一个类 class。在 Java 里 Int 不是 class。既然是 class,就有大量的方法。这一点,Scala 对数子类型的转换特别简洁。
比如:输入println(numl.to)时,to 这里有很多类型可以选择,tostring()、toByte、tochar、toDouble、toFloat、toInt 等等。想转什么类型都随便转。
② numl.toDouble 这里为什么没有小括号“numl.toDouble()”
写上()就会报错。
在 Scala 里,如果一个方法没有形参,可以省略()小括号。
def sayHi(): Unit= {
println("say hi")
def 是关键字,sayHi 是方法名,()是形参调整类型,: Unit= 返回值为空。这样是可以调用的。
写成 sayHi 或者 sayHi()两种都是可以执行调用的。
执行结果为:
D: \program\jdk8\bin\java…
10.0 10
say hi
say hi
这个小案例可以看出 Scala 语法特点是灵活、高效。
Scala 最难的地方就是在用它做一些算法设计。
总之,在 Scala 中数据类型都是对象。一切均为对象。
③ 数字常量、布尔值也认为是一个对象
继续上程序段编辑:
……
println(numl.toDouble+"\t"+num1.toString+100.toDouble)
var isPass = true //
printn(isPass.toString)
sayHi()
}
……
上程序段中100.toDouble这里的数字常量也认为是一个对象。
举布尔类型例子:
var isPass = true //
printn(isPass.toString)
这里用了类型推导。如果在 isPass 下边有波浪号,就代表 Declaration is never used,没有用。这种赋值却没有用处的,在其他语言里是会直接报错的。isPass.to 也有很多方法。
执行结果为:
D: \program\jdk8\bin\java
…
10.0
10100.0
true
say hi
(2)Scala 数据类型分为两大类,AnyVal 或者 AnyRef 都是对象。
[案例演示 Int , Char]
var num1 :Int = 10
printn("num1" + num1)
var char1 : Char= 'a'
printn("char1的code= " + char1 .toInt)
看下边的数据类型图:有一个根类型叫 Any,是所有类型的父类,下面的分两大类。
① AnyVal 类是值类型。值类型也是对象类型。
② AnyRef 类是引用类型。
引用类型类似于 Java 传统对象类型。
AnyRef 又分成三类:
(Scala collections)Scala 的集合。在 Java 基础上对这个集合进行扩展。
(all java classes)传统的 Java 的类。把 Java 的类融入到里面。所以说 Scala 融入了 Java。
(Other Scala classes)自定义类。可以自定义。或者其他不是这个集合里面的,都属于引用类型。
这就是传统的类或对象的范畴。
③ 实线箭头,代表继承的关系叫 Subtype。
比如:Char 或者 Boolean 类型是 AnyVal 的子类。同样,也可以认为 Scala collections 或者 Other Scala classes 类型是 AnyRef 的子类。AnyRef 或者 AnyVal 是 Any 的子类。
④ 在 Scala 里有两个特别的类型,一个是 Null,一个是 Nothing。
在 Scala 里有个专业的术语叫底层类。
底层类的作用:Null 是所有 AnyRef 的子类。Nothing 则是所有类的子类。Nothing 是最底层的类,Nothing 的数据可以赋值给任何一个变量,或者返回给任何一个函数。
一般在 Java 中,可以把一个类型返回给 object。但 Scala 设计者觉得还需优化加强。就设计一个类型是所有类的子类,这个类型的数据想赋值给谁就给谁。
Nothing 可以给任何一个,Byte/Char/Unit 等任何一个。
Scala 的设计在这个技术上做了扩展。
比如,throw 异常值,一般是往上层抛。在往上抛的时候,不知道接触这个异常的函数类型是什么类型,就有可能抛不上去。假如接收的类型不是这个异常的父类就抛不上去。设计者就把这个异常就做成 nothing 的类型。
⑤ 虚线箭头,implicit Conversion,叫隐式转换。
在 AnyVal 类中,byte 到 short 到 int 之间这些虚线箭头都是隐式。和 Java 一样,Scala 中仍然遵循由的低精度向高精度转换的规则。这是自动隐式转换,后面还会学到自定义隐式转换。
四、scala 数据类型体系一览图
对上图小结和整理
1、在 scala 中有一个根类型 Any,是所有类的父类。
2、 scala 中一切皆为对象,分为两大类 AnyVal(子类型),AnyRef(引用类型),都是 Any 子类。
3、 Null 类型是 scala 的特别类型,它只有一个值 null, 是 bottom class ,是所有 AnyRef 类型的子类。
4、Nothing 类型也是 bottom class ,是所有类的子类,在开发中通常可以将 Nothing 类型的值返回给任意变量或者函数,这里抛出异常使用很多。
以 Nothing 举例:
新建一个类,Create New Scala Class,Name为TypeDemo02,Kind为Object,打开编辑:
package com.atguigu.chapter02.datatype
object TypeDemo02 {
def main(args: Array[String]): Unit= {
println(sayHello)
}
//在开发中有一个方法,会异常中断,这时就可以返回 Nothing
//即当 Nothing 做返回值,就明确说明该方法没有正常返回值
def sayHello: Nothing= {
throw new Exception("抛出异常")
}
}
用 nothing 做返回值,说明该函数没有该方法,需要找方法,该方法没有正常的值。这种需求是有可能的。比如,在做大数据计算的时候,在某种情况下一定会出错。就可以用抓异常的方式来加入到业务逻辑。在学电信项目的时候,有时候抛异常本身也可以作为一种业务逻辑。在学习 Java 时,有学到 CRM 系统,就是用抛不同的异常来告诉客户是什么出错。比如,用户名、密码有问题。抛出一个异常,根据异常的类型来判断是什么问题。异常也可以成为逻辑判断
throw new Exception,这里的异常是 nothing 的子类。在 scala 中,异常可以随便抛。如:把 Nothing 换成Unit,这个空也能抛出去。
执行:
D: \program\jdk8\bin\java…
Exception in thread "main" java.lang.Exception:抛出异常
at com.atguigu.chapter02.datatype.TypeDemo02$.
sayHello(TypeDemo02.scala:11)
at com.atguigu.chapter02.datatype.TypeDemo02$.
main(IypeDemo02.scala:5)
at com.atguigu.chapter02.datatype.TypeDemo02.
main(TypeDemoo2.scala)
这就可以看到抛出的异常。
5、在 scala 中仍然遵守,低精度的值向高精度的值自动转换,叫做(implicit conversion)隐式转换。
例子:
…… Unit= {
println(sayHello)
var num= 1.2
//默认为 double
var num2= 1.7f
//这是 float
//num2 = num ,error ,修改 num2 = num.toFloat
}
……
设置 num 类型为1.2,给 num2赋一个 num,num2 = num 就会看到出错。
num 类型的数值默认为 double 类型,num2=1.7f 是 float 类型。这就会报错。
解决方案就是异型转换。将 num2 = num 改为 num2 = num.toFloat,转换数值类型为 Flaot。