注释
scala 注释 与 java 完全一样
//
单行注释
/*...*/
多行注释
/**...*/
文本注释注释
命名规范
Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化,有以下四种规则:
(1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)第一种和第二种拼接,第一种在前,二者以下划线分隔
(4)用反引号....
包括的任意字符串,即使是关键字(39个)也可以
案例
hello // ok
hello12 // ok
1hello // error
h-b // error
x h // error
h_4 // ok
_ab // ok
Int // ok , 因为在Scala Int是预定义的字符,不推荐
Float // ok
_ // error ,单独一个下划线不可以作为标识符
Abc // ok
+*- // ok
+a // error
$a // ok , 但不要让scala的标识符出现$,因为scala编译器会使用$
关键字
红色:scala 扩展的关键字
蓝色:scala 特定的语法
变量
变量是一种使用方便的占位符,用于引用计算机内存地址,变量创建后会占用一定的内存空间。
基于变量的数据类型,操作系统会进行内存分配并且决定什么将被储存在保留内存中。因此,通过给变量分配不同的数据类型,你可以在这些变量中存储整数,小数或者字母。
变量声明
在学习如何声明变量与常量之前,我们先来了解一些变量与常量。
一、变量: 在程序运行过程中其值可能发生改变的量叫做变量。如:时间,年龄。
二、常量 在程序运行过程中其值不会发生变化的量叫做常量。如:数值 3,字符'A'。
在 Scala 中,使用关键词 "var" 声明变量,使用关键词 "val" 声明常量。
声明变量实例如下:
var myVar : String = "Foo"
var myVar : String = "Too"
声明常量实例如下:可以理解java中的以 final 修饰的变量——常量
val myVal : String = "Foo"
以 var 修饰变量可以修改,而 val 修饰的变量是一个常量,是不可以变的
。
以上来自 菜鸟教程
在scala中是可以不用指定变量类型,能够自动转换。
var i = 10 // Int
var d = 2.3d // Double
var f = 2.3f // Float
var s = "hello" // String
var c ='a' // Char
var b = true // Boolean
使用 val 也是如此
val i = 10
val d = 2.3d
val f = 2.3f
val s = "hello"
val c ='a'
val b = true
也许这样,看不出来,此图(来自idea)
最后:官方推荐使用 val 修饰而不是 var。
字符串
定义字符串
val str="hello"
字符串的拼接
val str="hello"
val str1="world"
val str2 =str+str1 # helloworld
也可以使用 到java中的 的方法
val str2 =str concat(str1) # helloworld
或者简写
val str2 =str concat str1 # helloworld
以上两种方式都算是java的方式,那 scala 有什么方式呢?在scala支持 插值写入 的方式,该方式类似于 java中的 format。
语法:s"${}"
val str2 =s"${str}${str1}" # helloworld
或者简写
val str2 =s"$str$str1" # helloworld
既然类似于 java中的 format,那么在java中这里也是可以使用的
%s 表示字符串,除了%s,还有%d、%c 等;需要了解到童鞋可以看看这篇博客常规类型的格式化
val str2 = String.format("%s,%s",str,str1) #hello,world
字符串乘积输出;思考如何在控制台输出20个*?
方式一:
print("********************") # ********************
这种方式,优点费时,若是一万个 *
呢?当然你也可以编写函数,比如使用StringBuilder
。
在scala中有更优雅更简单的方式
print("*"*20) # ********************
其实scala底层源码就是采用StringBuilder
实现的
def * (n: Int): String = {
val buf = new StringBuilder
for (i <- 0 until n) buf append toString
buf.toString
}
千万不要使用 单引号('')
包括,否则会转换成unicode码
进行相乘。
print("*"*20) # 840
只有 scala 中的 字符串相关的方法,大部分都可使用 Java自带的。
转大写
val str ="hello"
println(str.toUpperCase) # HELLO
转小写
val str ="HELLO"
println(str.toLowerCase) # hello
截取
println(str.substring(0,2)) # he
关于其他方法就不写了,可以自行了解
输出打印
用于将结果打印到控制台,如同java中的System.out.println()
在scala中有三种输出打印方法
- println() :打印换行
- print() :打印不换行
- printf() :支持格式化打印
关于println()
和print()
就不讲了,很好理解;这里说一下 printf()
,可以用于格式化输出。
val i =1
val n1="小明"
val n2 ="小刚"
val d =5.3d
printf("%s花了%.2f钱,买了%d个苹果给%s",n1,d,i,n2) # 小明花了5.30钱,买了1个苹果给小刚
键盘输入
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。
StdIn.readLine()、StdIn.readShort()、StdIn.readDouble()...
引入StdIn
依赖
import scala.io.StdIn
接收一个用户输入
def main(args: Array[String]): Unit = {
print("请输入你的姓名:")
val r=StdIn.readLine()
print(s"你好;${r}同学")
}
// 请输入你的姓名:张三
// 你好;张三同学
除了 readLine
方法,还包含:
方法 | 参数值 |
---|---|
readLine | # 接收字符串 |
readBoolean | # 接收布尔类型 |
readByte | # 接收 Byte类型 |
readShort | # 接收 Short类型 |
readChar | # 接收 Char 类型 |
readInt | # 接收 Int 类型 |
readLong | # 接收 Long 类型 |
readFloat | # 接收 Float 类型 |
readDouble | # 接收 Double 类型 |
数据类型关系
AnyVal:数值类型
AnyRef:引用类型
StringOps:Scala 中对Java中的String增强
Unit:对应 Java中的void,用于方法返回值的位置,表示方法没有返回值。Unit是一个数据类型。只有一个对象就是()。void 不是数据类型,只是一个关键字。
Null:是一个类型,只有一个对象就是null。它是所有引用类型的(AnyRef)的子类
Nothing:是所有数据类型的子类,主要用在一个函数没有明确返回值时使用,因为这样我们可以把抛出的返回值,返回给任何的变量或者函数。
整数类型(Byte、Short、Int、Long)
Scala的整数类型就是用于存放整数值的,比如12,30,3456等等
数据类型 | 描述 |
---|---|
Byte [1] | 8位有符号补码整数。数值区间为 -128 到 127 |
Short [2] | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int [4] | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long [8] | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 = 2的(64-1)次方-1 |
案例:
def main(args: Array[String]): Unit = {
val by:Byte =10
val sho:Short =34
val i =10
val l =1000L
println(s"by=$by,by的类型=${by.getClass.getSimpleName}")
println(s"sho=$sho,sho=${sho.getClass.getSimpleName}")
println(s"i=$i,i的类型=${i.getClass.getSimpleName}")
println(s"l=$l,by的类型=${l.getClass.getSimpleName}")
}
结果:
by=10,by的类型=byte
sho=34,sho=short
i=10,i的类型=int
l=1000,by的类型=long
当然每种类型不能超过自己的作用范围;例如 byte
正确
var n1:Byte = 127
var n2:Byte = -128
错误
var n3:Byte = 128
var n4:Byte = -129
浮点类型(Float、Double)
Scala的浮点类型可以表示一个小数,比如123.4f,7.8,0.12等等。
数据类型 | 描述 |
---|---|
Float [4] | 32 位, IEEE 754标准的单精度浮点数 |
Double [8] | 64位 IEEE 754标准的双精度浮点数 |
案例:
def main(args: Array[String]): Unit = {
val f =10.23f
val d =56.25d
println(s"f=$f,f的类型=${f.getClass.getSimpleName}")
println(s"d=$d,d的类型=${d.getClass.getSimpleName}")
}
结果
f=10.23,f的类型=float
d=56.25,d的类型=double
字符类型(Char)
字符类型可以表示单个字符,字符类型是Char,16位无符号Unicode字符(2个字节),区间值为U+0000到U+FFFF。
案例
- 字符常量是用单引号 ' ' 括起来的单个字符。
- 可以直接给Char赋一个整数,然后输出时,会按照对应的unicode字符输出
def main(args: Array[String]): Unit = {
val man ='男'
val woman ='女'
val a ='a'
val b:Char=98
println(s"man=$man,f的类型=${man.getClass.getSimpleName}")
println(s"woman=$woman,woman的类型=${woman.getClass.getSimpleName}")
println(s"a的unicode=${a.toInt}")
println(s"b=$b")
}
结果:
man=男,f的类型=char
woman=女,woman的类型=char
a的unicode=97
b=b
在 java 可以实现 char 与 int 相加;char自动转为 int(隐式转换);在scala也是可以的。
val c ='a'+1
println(c) // 98
若要把int 转为 char 那么需要强制,在scala 中不能使用(类型)
的方式,而是需要用到 前面有介绍的 toXXX
函数
val c ='a'+1
println(c.toChar) // b
除了这些外,还支持转义字符;如下
符号 | 字符含义 |
---|---|
\n | 换行 (0x0a) |
\r | 回车 (0x0d) |
\f | 换页符(0x0c) |
\b | 退格 (0x08) |
\0 | 空字符 (0x0) |
\s | 空格 (0x20) |
\t | 制表符 |
" | 双引号 |
' | 单引号 |
\ | 反斜杠 |
\ddd | 八进制字符 (ddd) |
\uxxxx | 16进制Unicode字符 (xxxx) |
布尔类型:Boolean
- 布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false
- boolean类型占1个字节。
val bool1=true
val bool2:Boolean=false
Unit类型、Null类型和Nothing类型
数据类型 | 描述 |
---|---|
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null , Null 类型只有一个实例值null |
Nothing | Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性) |
- Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
- Unit类型用来标识过程,也就是没有明确返回值的函数。
由此可见,Unit类似于Java里的void。Unit只有一个实例——( ),这个实例也没有实质意义 - Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。
数值类型间转换
数值类型自动转换
当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
(2)当我们把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
def main(args: Array[String]): Unit = {
val i:Int =10
val l:Long=200
val r =i+l
println(s"r=$r,r的数据类型为${r.getClass.getSimpleName}") // r=210,r的数据类型为long
}
def main(args: Array[String]): Unit = {
val i:Int =10
val l:Long=200
val d:Double=56.23
val r =i+l+d
println(s"r=$r,r的数据类型为${r.getClass.getSimpleName}") // r=266.23,r的数据类型为double
}
(3)(byte,short)和char之间不会相互自动转换。
(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
def main(args: Array[String]): Unit = {
val b:Byte =1
val s:Short=2
val c:Char='a'
val r =b+s+c
println(s"r=$r,r的数据类型为${r.getClass.getSimpleName}")
}
r=100,r的数据类型为int
强制类型转换
在java中强制转换需要使用(类型)
的方式,scala中不支持这样操作,若需要强制转换那么就要使用到toXXX
函数
自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
def main(args: Array[String]): Unit = {
val i:Int =10
val d:Double=56.23
val ii=i.toDouble
val dd=d.toInt
println(s"ii=$ii,ii的数据类型为${ii.getClass.getSimpleName}") // ii=10.0,ii的数据类型为double
println(s"dd=$dd,dd的数据类型为${dd.getClass.getSimpleName}") // dd=56,dd的数据类型为int
}
上面有演示
Char类型可以保存Int的常量值,但不能保存Int的变量值,需要强转
Byte和Short类型在进行运算时,当做Int类型处理。
数值类型和String类型间转换
在程序开发中,我们经常需要将基本数值类型转成String类型。或者将String类型转成基本数值类型。
基本类型转String类型
方式一:(语法:将基本类型的值+"" 即可)
def main(args: Array[String]): Unit = {
val i =10
val r="aa"+i
println(r) // aa10
}
方式二:*.toString
def main(args: Array[String]): Unit = {
val i=65
val ii=i.toString
println(s"ii=$ii,ii的数据类型为${ii.getClass.getSimpleName}") // ii=65,ii的数据类型为String
}
String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)
如:字符串转 Double
def main(args: Array[String]): Unit = {
val s1="52.36"
val ii=s1.toDouble
println(s"ii=$ii,ii的数据类型为${ii.getClass.getSimpleName}") //ii=52.36,ii的数据类型为double
}
注意:
在将String类型转成基本数值类型时,要确保String类型能够转成有效的数据,比如我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数。
运算符
算术运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | b=4; | -b -4 |
+ | 加 | 5+5 | 10 |
- | 减 | 6-4 | 2 |
* | 乘 | 3*4 | 12 |
/ | 除 | 5/5 | 1 |
% | 取模(取余) | 7%5 | 2 |
+ | 字符串相加 | “He”+”llo” | “Hello” |
(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
(2)对一个数取模a%b,和Java的取模规则一样
关系运算符(比较运算符)
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | false |
!= | 不等于 | 4!=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
逻辑运算符
用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个Boolean值。
假定:变量A为true,B为false
运算符 | 描述 | 实例 |
---|---|---|
&& | 逻辑与 | (A && B) 运算结果为 false |
|| | 逻辑或 | (A || B) 运算结果为 true |
! | 逻辑非 | !(A && B) 运算结果为 true |
赋值运算符
赋值运算符就是将某个运算后的值,赋给指定的变量。
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,将一个表达式的值赋给一个左值 | C = A + B 将 A + B 表达式结果赋值给 C |
+= | 相加后再赋值 | C += A 等于 C = C + A |
-= | 相减后再赋值 | C -= A 等于 C = C - A |
*= | 相乘后再赋值 | C *= A 等于 C = C * A |
/= | 相除后再赋值 | C /= A 等于 C = C / A |
%= | 求余后再赋值 | C %= A 等于 C = C % A |
<<= | 左移后赋值 | C <<= 2 等于 C = C << 2 |
>>= | 右移后赋值 | C >>= 2 等于 C = C >> 2 |
&= | 按位与后赋值 | C &= 2 等于 C = C & 2 |
^= | 按位异或后赋值 | C ^= 2 等于 C = C ^ 2 |
|= | 按位或后赋值 | C |= 2 等于 C = C | 2 |
注意:Scala中没有++、--操作符,需要通过+=、-=来实现同样的效果
位运算符
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> | 右移动运算符 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
>>> | 无符号右移 | A >>>2 输出结果 15, 二进制解释: 0000 1111 |
scala 中实现 i++ 及 i-- 操作
i++
def main(args: Array[String]): Unit = {
var i=0;
i-=1
println(i) // -1
}
i--
def main(args: Array[String]): Unit = {
var i=0;
i+=1
println(i) // 1
}
至于为什么 scala 不支持 i++ 及 i--;大部分网友说,开发者认为i++ ,i-- 可读性太差,理解起来不好。
比如:
public static void main(String[] args) {
int a=10;
a=a++;
a=a++;
a=a++;
System.out.println("a="+a);
int b=10;
b=++b;
b=++b;
b=++b;
System.out.println("b="+b);
}
思考一下,a=多少?b=多少?
a=10
b=13
i+=,i-= 的方式;理解起来就会简单很多
public static void main(String[] args) {
int a=10;
a+=1;
a+=1;
a+=1;
System.out.println("a="+a);
int b=10;
b-=1;
b-=1;
b-=1;
System.out.println("b="+b);
}
a=13
b=7