Scala语法基础
一.变量与数据类型
1.注释
1)Scala注释使用和Java完全一样
- 单行注释://
- 多行注释:/* */
- 文档注释:/** */
2)操作文档——API
scaladoc -d ./doc scala文件名
命令 参数[文档] 操作文档放到当前目录下的doc文件夹
3)代码规范:
- ctrl + alt + L来进行格式化
- 一行最长不超过80个字符,超过的请使用换行展示
- 运算符两边习惯性各加一个空格
2.变量与常量*
1)基本语法:
var 变量名[: 变量类型] = 初始值 ==> var i:Int = 10
val 常量名[: 常量类型] = 初始值 ==> val j:Int = 20
注意:能用常量的地方不用变量
注意事项:
- 类型推到
- 强类型语言
- 必备初始值
- 常量不可变(除非是对象自己本身属性)
案例
//(1)声明变量时,类型可以省略,编译器自动推导,即类型推导
var age = 18
age = 30
//(2)类型确定后,就不能修改,说明Scala是强数据类型语言。
age = "tom" // 错误
//(3)变量声明时,必须要有初始值
var name // 错误
//(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改。
var num1 = 10 // 可变
val num2 = 20 // 不可变
num1 = 30 // 正确
num2 = 100 //错误,因为num2是val修饰的
//(5)var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)
var p1 = new Person() //变量
p1.name = "dalang"
p1 = null
val p2 = new Person() //常量
p2.name="jinlian"
p2 = null // 错误的,因为p2是val修饰的
在实际开发中,var与val默认选谁?
- 例:在java中,创建一个变量,将不同的对象赋值给变量的情形较少。
- 所以:能用常量的地方不用变量
3.标识符与命名规则
Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化,有以下四种规则:
(1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)用反引号`…`包括的任意字符串,即使是Scala关键字(39个)也可以
- package, import, class, object, trait, extends, with, type, for
- private, protected, abstract, sealed, final, implicit, lazy, override
- try, catch, finally, throw
- if, else, match, case, do, while, for, return, yield
- def, val, var
- this, super
- new
- true, false, null
4.字符串输出
基本语法
- 1)字符串,通过+号连接
- 2)printf用法:字符串,通过%传值——%d %f %s
- 3)字符串模板(插值字符串):通过${ }获取变量值,在字符串前,需要加s/f/raw进行标记
- 4)""" “”" :保持字符串原样输出,格式对其——stripMargin,默认是“|”作为连接符
object TestCharType {
def main(args: Array[String]): Unit = {
var name: String = "jinlian"
var age: Int = 18
//(1)字符串,通过+号连接
println(name + " " + age)
//(2)printf用法字符串,通过%传值。
printf("name=%s age=%d\n", name, age)
//(3)字符串,通过$引用
//多行字符串,在Scala中,利用三个双引号包围多行字符串就可以实现原格式输出。
//输入的内容,带有空格、\t之类,导致每一行的开始位置不能整洁对齐。
//应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为连接符,//在多行换行的行头前面加一个“|”符号即可。
val s =
"""
|select
| name,
| age
|from user
|where name="zhangsan"
""".stripMargin
println(s)
//如果需要对变量进行运算,那么可以加${}
val s1 =
s"""
|select
| name,
| age
|from user
|where name="$name" and age=${age+2}
""".stripMargin
println(s1)
val s2 = s"name=$name"
println(s2)
}
}
5.键盘输入
基本语法:
- StdIn.readLine()
- StdIn.readShort()
- StdIn.readDouble()
6.数据类型*
java中:
- 基本数据类型:四类八种
- char、byte、short、int、long、float、double、boolean
- 引用数据类型
- 由于Java有基本类型,而且基本类型不是真正意义的对象
- Java基本类型的包装类:Character、Byte、Short、Integer、Long、Float、Double、Boolean
注意:Java中基本类型和引用类型没有共同的祖先。
- Scala中一 切数据都是对象,都是Any的子类
- Scala中数据类型分为两大类:数值类型( AnyVal)、引用类型(AnyRef),不管是值类型还是引用类型都是对象。
- Scala数据类型仍然遵守,低精度的值类型向高精度值类型,自动转换(隐式转换)
- Scala中的StringOps是对Java中的Sting增强
- Unit:对应Java中的void,用于方法返回值的位置,表示方法没有返回值。Unit是一个数据类型, 只有一个对象就是( )。Void不是数据类型,只是一个关键字
- Null是一个类型,只有一个对象就是null,它是所有引用类型(AnyRef) 的子类。
- Nothing, 是所有数据类型的子类,主要用在一个函数没有明确返回值时使用,因为这样我们可以把抛出的返回值,返回给任何的变量或者函数。
1)整数类型(Byte、Short、Int、Long)
Byte、Short、Int、Long:
- 字节数 1、2、4、8
- 采用二进制补码存储
- 默认Int类型
注意:
- 在编译的时候,会判断当前数值是否在当前类型表示范围之内。如果在,底层默认进行转换
- Scala程序中变量常声明为Int型(默认类型),除非不足以表示大数,才使用Long
- 声明Long型,须后加‘l’或‘L’
//这个编译会通过,如果报错可能是IDEA支持性不好
var b:Byte = 10 + 20
var b1:Byte = 10
//此时会报错:编译不会通过
var b2:Byte = b1 + 20
// 正确
var n1:Byte = 127
var n2:Byte = -128
// 错误
// var n3:Byte = 128
// var n4:Byte = -129
// Long型
var n6 = 9223372036854775807L
println(n6)
2)浮点类型(Float、Double)
Scala的浮点类型可以表示一个小数:Float、Double
- 字节数:4、8
- 浮点型常量默认为Double型,声明Float型常量,须后加‘f’或‘F’
3)字符型(Char)
字符类型可以表示单个字符,字符类型是Char
- 字符常量是用单引号 ’ ’ 括起来的单个字符
4)布尔类型(Boolean)
基本说明
- 1)布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false
- 2)boolean类型占1个字节。
7.Unit类型、Null类型和Nothing类型*
数据类型 | 描述 |
---|---|
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。 Unit只有一个实例值,写成( )。 |
Null | null , Null 类型只有一个实例值null Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal) |
Nothing | Nothing类型在Scala的类层级最低端;它是任何其他类型的子类型。 当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(如-异常)赋给其它的函数或者变量,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容(兼容性) |
object TestSpecialType {
def main(args: Array[String]): Unit = {
// 1.unit表示没有返回值,即void
def sayOk : Unit = {
}
println(sayOk)
//2.null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
var cat = new Cat();
cat = null // 正确
var n1: Int = null // 错误
println("n1:" + n1)
//3.Nothing
def test : Nothing={
throw new Exception()
}
test
}
}
8.类型转换
扩展Java面试题(隐式类型转换):
public static void main(String[ ] args) {
byte b = 10;
test(b);
}
public static void test(byte b) {
System.out.println("bbbb");
}
public static void test(short s) {
System.out.println("sssss");
}
public static void test(char c) {
System.out.print1n("cccc");
}
public static void test(int i) {
System.out.print1n("iiii");
}
test(b):
- 会先调用test(byte b)方法,
- 如果注释掉test(byte b),则调用test(short s),因为其补位最少
- 再注释,调用test(int i)
- 不会调用test(char c),因为char是无符号整数,byte有符号整数
1)数值类型自动转换
当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
基本说明:
(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
(3)(byte,short)和 char 之间不会相互自动转换。
(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型
2)强制类型转换
基本说明:
- 自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型
- 使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意
- 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
Java : int num = (int)2.5
Scala : var num : Int = 2.7.toInt
object Test {
def main(args: Array[String]): Unit = {
//(1)将数据由高精度转换为低精度,就需要使用到强制转换
var n1: Int = 2.5.toInt // 这个存在精度损失
println(n1) // 值为:2
//(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
var r1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt // 10 *3 + 6*1 = 36
var r2: Int = (10 * 3.5 + 6 * 1.5).toInt // 44.0.toInt = 44
println("r1=" + r1 + " r2=" + r2)
}
}
3)数值类型和String类型间转换
- 基本类型转String类型(语法:将基本类型的值+"" 即可)
- String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)
//(1)基本类型转String类型(语法:将基本类型的值+"" 即可)
var str1 : String = true + ""
var str2 : String = 4.5 + ""
var str3 : String = 100 +""
//(2)String类型转基本数值类型(语法:调用相关API)
var s1 : String = "12"
var n1 : Byte = s1.toByte
var n2 : Short = s1.toShort
var n3 : Int = s1.toInt
var n4 : Long = s1.toLong
注意事项:
- 在将String类型转成基本数值类型时,要确保String类型能够转成有效的数据
- 比如我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数
var n5:Int = "12.6".toInt //会出现NumberFormatException异常。
二.运算符
5类运算符
1.算数运算符:+ - * / %
2.关系运算符
Java和Scala中关于==的区别:
1)Java:
- ==比较两个变量本身的值,即两个对象在内存中的地址;
- equals( )方法,其底层也是==,但是部分类重写了Object类的equals( )方法。如字符串就是比较字符串中所包含的内容是否相同。
2)Scala:
- ==更加类似于Java中的equals,比较的是内容是否相同——参照jd工具
- ==底层调用的equals()方法
- 若需要比较两个对象的地址是否相等:eq( )方法
def main(args: Array[String]): Unit = {
val s1 = "abc"
val s2 = new String("abc")
println(s1 == s2)
println(s1.eq(s2))
}
输出结果:
true
false
3.逻辑运算符
- 短路与:&&
- 短路或:||
- 非:!
//java扩展:java中避免逻辑与空指针异常,使用短路与&&
isNotEmpty(String s){
//如果逻辑与,s为空,会发生空指针
return s!=null && !"".equals(s.trim());
}
4.赋值运算符
-
注意:Scala中没有++、- -操作符,可以通过+=、- =来实现同样的效果;
-
扩展:scala中 += 没有Java中的强转功能 ;
def main(args: Array[String]): Unit = {
var r1 = 10
r1 += 1 // Scala没有++
r1 -= 2 // Scala没有--
//在Java语言中, +-运算符可以自动进行强转
//但是在scala语言中:+-底层不会自动进行强转:
var b:Byte = 10
b += 1 //运行会报错,效果与 b = b + 1 一致
println(b)
}
5.位运算符
下表中变量 a 为 60,b 为 13。
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符 | a << 2 输出结果 240 ,二进制解释: 0011 0000 |
>> | 右移动运算符 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
>>> | 无符号右移 | a >>>2 输出结果 15, 二进制解释: 0000 1111 |
Scala运算符本质*
在Scala中其实是没有运算符的,所有运算符都是方法:
- 1)当调用对象的方法时,点.可以省略
- 2)如果函数参数只有一个,或者没有参数,()可以省略
def main(args: Array[String]): Unit = {
// 标准的加法运算
val i:Int = 1.+(1)
// (1)当调用对象的方法时,.可以省略
val j:Int = 1 + (1)
// (2)如果函数参数只有一个,或者没有参数,()可以省略
val k:Int = 1 + 1
//三者输出效果一致:都是 1
println(1.toString())
println(1 toString())
println(1 toString)
}