1. Scala 与 Java 的关系
Scala 和 Java 都是运行在 JVM 上。
Scala 可以调用 Java 的类库,在语法上较 Java 更为简洁
Scala 将函数式编程和面向对象思想完美的结合
2. 基本语法
class Hello {
/*
定义变量: val 代表常量;var 代表变量
val/var 变量名:变量类型 = 变量值
*/
val a: Int = 1
/*
定义方法:
def 函数名(参数名:参数类型):返回值类型={方法体}
*/
def hello(arg: String): Unit = {
println(arg)
}
}
object Hello {
// Scala程序的入口
def main(args: Array[String]): Unit = {
println("hello,scala")
}
/*
完全面向对象:scala 完全面向对象,故 scala 去掉了 java 中非面向对象的元素,如 static 关键字,void 类型
1.static
scala 无 static 关键字,由 object 实现类似静态方法的功能(类名.方法名),object 关键字和 class 的关键字定义方式相同,但作用不同。class 关键字和 java 中的 class 关键字作用相同,用来定义一个类;object 的作用是<front color:green>声明一个单例对象<front color>,object 后的“类名”可以理解为该单例对象的变量名。
2.void
对于无返回值的函数,scala 定义其返回值类型为 Unit 类,Unit 只有一个 Null 对象。
*/
}
3. 运行原理
- object 在底层会生成两个类
Hello
,Hello$
- Hello 中有个 main 函数,调用
Hello$
类的一个静态对象MODULES$
-
Hello$.MODULES$.对象
是静态的,通过该对象调用Hello$
的 main 函数 - 在 main 中写的代码在放在
Hello$
的 mian 中,Scala 编译器在底层做了包装 - Scala 程序的执行入口时 object 中的 mian() 函数
/* Hello 源代码 */
object Hello {
def main(args: Array[String]): Unit = {
//4. 可以理解我们在 main 中写的代码在放在 Hello$ 的 main,在底层执行 scala 编译器做了一个包装
println("hello,scala")
}
}
//1. object 在底层会生成两个类 Hello , Hello$
/* Hello.class 类 */
//2. Hello 中有个 main 函数,调用 Hello$ 类的一个静态对象 MODULES$
public final class Hello
{
public static void main(String[] paramArrayOfString)
{
Hello$.MODULE$.main(paramArrayOfString);
}
}
/* Hello$.class 类 */
public final class Hello$
{
public static final MODULE$;
static { new (); }
public void main(String[] args)
{
//3. Hello$.MODULE$. 对象是静态的,通过该对象调用 Hello$ 的 main 函数
Predef..MODULE$.println("hello,scala");
}
private Hello$()
{
MODULE$ = this;
}
}
说明:
- Scala 中如果使用 object 关键字声明类,在编译时会同时生成两个类:
当前类
,当前类$
- 使用
当前类$
的目的在于模拟静态语法,可以通过类名直接访问方法。 - Scala 将
当前类$
这个对象称之为“伴生对象”,伴随着类所产生的对象,这个对象中的方法可以直接使用。
总结:object 对象名 中的 mian() 方法就是对象名$
中的MODULES$
的 mian()
4. 字符串输出
4.1 格式化输出 printf
字符串,通过 % 传值。
val a = 10
// 格式化输出
printf("a的值是: %d %.2f %s", a, 2.888, "abc")
a的值是: 10 2.89 asc
4.2 模板输出
三重引号中间可以使用模板输出,方便多行带缩进的代码,方便 SQL
val s =
"""
|select
| name,
| age,
| gender
|from user
|where name='zhangsan';
""".stripMargin
print(s)
4.3 字符串变量赋值输出
可以使用 ${变量} 的形式传值,{ } 内也可以进行计算
val name = "zhangsan"
val age = 20
val b =
s"""
|select
| name,
| age,
| gender
|from user
|where name='${name}' and age=${age + 2};
""".stripMargin
println(b)
5. 键盘输入
三种常用的输入,Stdln.readLine、Stdln.readShort、Stdln.readDouble
//1. 输入姓名
val name = StdIn.readLine("请输入姓名")
//2. 输入年龄
print("请输入年龄:")
val age = StdIn.readShort()
//3. 输入薪水
print("请输入薪水:")
val salary = StdIn.readDouble()
6.数据类型
基本数据类型
- Scala 中一切数据都是对象,都是 Any 的子类
- Scala 中数据类型分为两大类:数值类型(AnyVal)、引用类型(AnyRef),这两种类型都是对象
- Scala 数据类型遵循低精度向高精度自动转换(隐式转换)
- Scala 特殊的类型之 Null,它只有一个实例就是 null,它是所有引用类型的(AnyRef) 的子类
- Boolean:true / false
- Unit 类型:无值,和 java 中 void 等同。用作不返回任何结果的方法的结果类型。Unit 只有一个实例值,写成 ()
- StringOps 类型:对 Java 中 String 类型的扩展
- Nothing 类型:Nothing 类型在 Scala 的类层级的最低端;它是任何其他类型的子类型。当一个函数,我们确定没有正常的返回值,可以用 Nothing 来指定返回类型(联想 java 的多态),这样可以把返回的值(异常)赋给其它的函数或者变量(兼容性)
7. 类型转换
自动类型转换
强制类型转换
将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
// Char类型可以保存Int的常量值,但不能保存Int的变量值,需要强转
var c2: Char = 98 // 正确,因为直接将一个数值给char,编译器只判断是否越界
var c3: Char = 'a' + 1 // 错误,Int高->char低,编译器判断类型
var c4: Char = ('a' + 1).toChar // 正确,先提升成 Int,在强转成 Cahr,输出 b
// Byte和Short类型在进行运算时,当做Int类型处理。
var a : Short = 5
a = a-2 // 错误, Int->Short
var b : Byte = 3
b = b + 4 // 错误,Int->Byte
8. 运算符
- 对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
var r1: Int = 10 / 3 // 3
println("r1=" + r1)
var r2: Double = 10 / 3 // 3.0
println("r2=" + r2)
var r3: Double = 10.0 / 3 // 3.3333
println("r3=" + r3)
println("r3=" + r3.formatted("%.2f")) // 保留小数点2位,使用四舍五入
- 在做比较时 == 的作用和 java 中的 .equals() 方法类似,而 = 则更多的是使用 .eq 来操作
- Scala 中没有++、--操作符,需要通过 +=、-= 来实现同样的效果
- 本质上 Scala 中没有任何的运算符,因为所有的运算符都是函数
9. 流程控制
9.1 if else
if else 语句和 java 类似,但是,Scala 中 if else 是有返回值的,返回值取决于满足条件的代码体的最后一行内容。
Scala 没有 switch case 结构,有一种更强大的结构(模式匹配)。
9.2 for 遍历
// 1.前闭后闭,i 从1循环到3
for(i <- 1 to 3){
print(i + " ")
}
1 2 3
// 2.前闭后开,i 从1循环到2
for(i <- 1 until 3){
print(i + " ")
}
1 2
// 3.循环守卫,加入条件 if i != 3,当i不等于3时满足条件,即输出时跳过3,类似于 java 中的 continue
for (i <- 1 until 10 if i != 3) {
print (i + " ")
}
1 2 4 5 6 7 8 9
// 4.循环步长,by 表示步长
for (i <- 1 to 10 by 2) {
print(i +" ")
}
1 3 5 7 9
// 5.嵌套循环,注意此处没有关键字,所以范围后要加;来隔断逻辑
// 注意:只有当所有的逻辑在内循环中,才可以将两个循环成一个for
for (i <- 1 to 2; j <- 1 to 3) {
println("i=" + i + "j=" + j)
}
i=1j=1
i=1j=2
i=1j=3
i=2j=1
i=2j=2
i=2j=3
// 6.引入变量
// 引入变量
for (i <- 1 to 3; j = 4 - i) {
println("i=" + i + "j=" + j)
}
i=1j=3
i=2j=2
i=3j=1
// 7.循环返回值,将循环中的所有值*2,并将结果返回到新的集合中
val res = for(i <- 1 to 10) yield {
i * 2
}
println(res)
9.3 While 循环
while 语句没有返回值,即整个 while 语句的结果是 Unit 类型 ()
// while 循环与 java 中类似
var i = 0
while (i < 10) {
println(i+" ")
i += 1
}
注:因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量造成了影响,也就违背了函数式编程的重要思想(输入=>函数=>输出,不对外界造成影响),所以不推荐使用,而是 推荐使用 for 循环
9.4 循环终止
Scala 为更好的适应函数式编程,使用 breakable() 方法和 break() 方法控制结构来实现 break 和 continue 功能。
Scala 的循环终止,本质上是用抛异常的并捕获异常的方式 解决的,分别用 break() 方法抛异常,用 breakable() 方法捕获
import util.control.Breaks._
// 实现 break 功能
var i = 0
breakable {
while (i < 10) {
println("i=" + i)
i += 1
if (i == 5) break()
}
}
// 实现 continue 功能
var j = 0
while (j < 10) {
breakable {
j += 1
if (j == 5) break()
println("j=" + j)
}
}
注:break:breakable 放在循环外;continue:breakable 放在循环内