Scala快速入门+示例

news/2024/12/20 11:40:04/

目录

  • 定义和描述
  • idea
  • 基础
    • 关键字
    • 变量、常量
    • 输出
    • 数据类型
    • 类型转换
  • 函数式编程
    • 函数和方法的区别
      • 定义示例
        • 有参+带返回值
        • 有参+没有返回值
    • 注意点
  • 面向对象
    • object和class的区别
    • 对象的属性

快速上手使用版


定义和描述

基于JVM的语言,支持面向对象、面向函数,支持JVM和JavaScript
官网

Spark基于scala进行开发,Flink也提供了关于scala相应的API

idea

idea可能无法正常添加scala的框架(添加框架支持这个方法确实不行)
此处提供另一种办法
先安装scala插件
项目结构---->>库---->>添加scala的sdk

基础

关键字

关键字描述示例
package定义一个包package com.example.myapp
import导入其他包或对象中的成员import scala.collection.mutable.ListBuffer
class定义一个类class Person(val name: String, val age: Int)
object定义一个单例对象object MainApp extends App { println("Hello, World!") }
trait定义一个特质trait Logger { def log(msg: String): Unit }
extends用于类的继承class Student(name: String, age: Int) extends Person(name, age)
with用于混入特质或多个特质class Admin extends Person("Admin", 0) with Logger
type定义类型别名或类型成员type Name = String
for用于循环和推导式for (i <- 1 to 5) println(i)
private定义一个私有成员class MyClass { private val secret = "secret" }
protected定义一个受保护成员class Parent { protected val protectedVal = 1 }
abstract定义一个抽象类或抽象方法abstract class Animal { def makeSound: Unit }
sealed限定类的继承sealed trait Shape
final禁止类或方法被重写或继承final class Constants { val Pi = 3.14 }
implicit定义一个隐式值或隐式转换implicit val defaultTimeout: Int = 5000
lazy定义一个惰性变量lazy val lazyVal = { println("Computing..."); 42 }
override重写父类或特质中的方法class Dog extends Animal { override def makeSound = println("Woof") }
try捕获异常的代码块try { val x = 1 / 0 } catch { case _: ArithmeticException => println("Division by zero!") }
catch捕获异常并处理同上
finally无论是否发生异常,都会执行的代码块try { ... } finally { println("Cleanup!") }
throw抛出一个异常throw new IllegalArgumentException("Invalid argument!")
if条件语句val x = if (a > b) a else b
else与if语句结合使用,表示其他情况同上
match模式匹配语句val msg = num match { case 1 => "One" case _ => "Other" }
case在match语句中使用,表示一个匹配项同上
do与while结合使用,表示循环体do { println("Looping...") } while (condition)
while条件循环while (condition) { println("Looping...") }
return从方法中返回值def add(a: Int, b: Int): Int = { return a + b }
yield在推导式(如for-comprehension)中产生一个值val squares = for (i <- 1 to 5) yield i * i
def定义一个方法def greet(name: String): String = s"Hello, $name!"
val定义一个不可变变量val x = 10
var定义一个可变变量var y = 20; y = 30
this指向当前对象或类的实例class MyClass { def printThis = println(this) }
super指向父类或特质的实例class Child extends Parent { def callParentMethod = super.parentMethod }
new创建对象或类的实例val person = new Person("John", 30)
true布尔值真val isTrue = true
false布尔值假val isFalse = false
null表示空值或不存在的对象val emptyString: String = null

变量、常量

变量、常量初始化时,必须定义其值

scala">object VariableExample {def main(args: Array[String]): Unit = {// 定义不可变变量val name: String = "Alice"// 或者省略类型注解,因为编译器可以推断出它是String类型val age = 30// 打印变量的值println(s"Name: $name, Age: $age")// 定义可变变量var count: Int = 0// 修改可变变量的值count = count + 1// 打印修改后的值println(s"Count: $count")// 尝试修改不可变变量会导致编译错误// name = "Bob" // 这行代码会导致编译错误,因为name是不可变的// var a	//错误,必须定义值}
}

输出

java的System.out.println也可以,因为允许混编

scala">object PrintExample {def main(args: Array[String]): Unit = {// 使用println打印,并自动换行println("Hello, World!")// 使用print打印,不换行print("Hello, ")print("Scala!")// 你也可以打印变量和表达式的值val name = "Alice"val age = 30println(s"Name: $name, Age: $age")  // 使用字符串插值// 打印数组或集合val numbers = Array(1, 2, 3, 4, 5)println(numbers.mkString(", "))  // 使用mkString方法将数组转换为字符串}
}

数据类型

在这里插入图片描述

数据类型描述示例
Byte8位有符号补码整数。数值区间为 -128 到 127val byteVal: Byte = 100
Short16位有符号补码整数。数值区间为 -32768 到 32767val shortVal: Short = 20000
Int32位有符号补码整数。数值区间为 -2147483648 到 2147483647val intVal: Int = -1000000
Long64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807val longVal: Long = 9223372036854775807L
Float32位, IEEE 754 标准的单精度浮点数val floatVal: Float = 3.14f
Double64位 IEEE 754 标准的双精度浮点数val doubleVal: Double = 3.141592653589793
Char16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFFval charVal: Char = ‘A’
Booleantrue或falseval booleanVal: Boolean = true
Unit表示无值,和Java语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。def printHello(): Unit = println(“Hello, World!”)
String字符序列val stringVal: String = “Hello, Scala!”
Nullnull 或空引用(在Scala中应尽量避免使用null,更推荐使用Option类型来处理可能的空值)var nullableVal: String = null // 尽量避免这样做
NothingNothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。通常用于表示从不正常终止的函数(如抛出异常的函数)。def error(): Nothing = throw new Exception(“An error occurred”)
AnyAny是所有其他类的超类val anyVal: Any = “This can be any type”
AnyRefAnyRef类是Scala里所有引用类(reference class)的基类(相当于Java中的Object)val anyRefVal: AnyRef = new Object()
AnyValAnyVal类是Scala里所有值类(如Int, Double等)的基类(注意:AnyVal本身不是一个具体的类型,而是一个特性标记,用于优化值类型的处理)// AnyVal是一个抽象概念,不直接用于定义变量

注意

  1. 在Scala中,对于数值类型(如Byte, Short, Int, Long),当值超过其表示范围时,会发生类型溢出。
  2. 对于Float和Double类型的浮点数,由于精度限制,某些小数可能无法精确表示。
  3. 在Scala中,应尽量避免使用null值,因为null值可能导致运行时错误(如NullPointerException)。相反,Scala提供了Option类型来处理可能的空值情况。
  4. Nothing类型通常用于表示从不返回正常结果的函数(如总是抛出异常的函数)。在实际编程中,你很少需要直接声明Nothing类型的变量或返回值。
  5. Any和AnyRef是Scala类型系统的顶层类型。Any是所有类型的超类,包括值类型和引用类型;而AnyRef是所有引用类型的超类(不包括值类型)。

类型转换

在这里插入图片描述
显示类型转换

scala">object ExplicitTypeConversion {def main(args: Array[String]): Unit = {// 将Double转换为Int,注意这可能会导致精度丢失val doubleValue: Double = 123.45val intValue: Int = doubleValue.toInt // 显式类型转换println(s"Double to Int: $intValue") // 输出: Double to Int: 123// 将String转换为Intval stringValue: String = "456"val intValueFromString: Int = stringValue.toInt // 这要求字符串内容是一个有效的整数println(s"String to Int: $intValueFromString") // 输出: String to Int: 456// 将Any类型转换为具体类型(假设你知道它的实际类型)val anyValue: Any = "789"val stringFromAny: String = anyValue.asInstanceOf[String] // 显式类型转换,要求实际类型匹配println(s"Any to String: $stringFromAny") // 输出: Any to String: 789}
}

隐式类型转换

scala">object ImplicitTypeConversion {def main(args: Array[String]): Unit = {// 隐式地将Byte转换为Intval byteValue: Byte = 10val sum: Int = byteValue + 20 // 在这里,byteValue会被隐式地提升为Int类型println(s"Byte to Int (implicit): $sum") // 输出: Byte to Int (implicit): 30// 使用Scala的RichInt、RichDouble等隐式转换val intValue: Int = 10val bigIntValue: BigInt = intValue // RichInt提供了到BigInt的隐式转换println(s"Int to BigInt (implicit): $bigIntValue") // 输出: Int to BigInt (implicit): 10}
}

函数式编程

函数和方法的区别

  1. Scala 中存在方法与函数两个不同的概念,二者在语义上的区别很小。scala 方法是类的一部分,而函数是一个对象,可以赋值给一个变量,也可以作为方法或其它函数的参数。换句话来说在类中定义的即是方法scala 中的方法跟 Java 的类似,方法是组成类的一部分。scala 中的函数则是一个完整的对象。

  2. Scala中的方法和函数从语法概念上来讲,一般不好区分,所以简单的理解就是:方法也是函数。只不过类中声明的函数称之为方法,其他场合声明的就是函数了。类中的方法是有重载和重写的。而函数没有重载和重写的概念,但是函数可以嵌套声明使用,方法不行

特性方法(Method)函数(Function)
定义位置类的一部分独立的对象,可以赋值给变量,作为参数传递
语义区别在类中定义的即是方法在类外部或其他场合声明的称为函数
与Java的关系与Java的方法类似是Scala特有的完整对象
重载与重写支持重载和重写不支持重载和重写
嵌套声明不能嵌套声明使用可以嵌套声明使用

定义示例

有参+带返回值

冒号后面定义的是String表示返回一个String类型的值,如何返回则是在整个函数体的末尾
以下示例代码结果是”wunaiieq“而不是"hello world"

scala">package com.wunaiieqobject Example {def main(args: Array[String]): Unit = {/**@param arg 定义的参数,String类型* @return 冒号后面定义的是String表示返回一个String类型的值,如何返回则是在整个函数体的末尾* */def f1(arg: String): String = {arg + " world""wunaiieq"}println(f1("hello"))}
}
有参+没有返回值
scala">package com.wunaiieqobject VariableExample {def main(args: Array[String]): Unit = {/**@param arg 定义的参数,String类型* @return 冒号后面定义的是Unit表示没有返回值* */def f1(arg: String): Unit = {arg + " world""wunaiieq"}}
}

注意点

  1. 函数定义语法 用def来定义

  2. 可以定义传入的参数,要指定传入参数的类型

  3. 函数可以写返回值的类型也可以不写,会自动推断,有时候不能省略,必须写,比如在递归函数中或者函数的返回值是函数类型的时候。

scala">def funcD3(name:String,score:Double){//....//return s"有参数有返回值,Hello ${name},your score is ${score}"s"有参数有返回值,Hello ${name},your score is ${score}"
}
println(funcD3("diaosi",100))
输出结果为:()
  1. scala中函数有返回值时,可以写return,也可以不写return,会把函数中最后一行当做结果返回。当写return时,必须要写函数的返回值。

  2. 如果函数体可以一行搞定,可以将函数定义时的{}省略不写

  3. 传递给函数的参数可以在函数中使用,并且scala规定函数的传过来的参数为val的,不是var的。

  4. 如果去掉函数体前面的等号,那么这个方法返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit.假设,里面的逻辑最后返回了一个String,那么这个返回值会被转换成Unit,并且值会被丢弃。

面向对象

object和class的区别

特性objectclass
实例化单例,只能有一个实例可以有多个实例
实例创建实例在对象定义时自动创建,不能通过new关键字实例化使用new关键字来实例化
继承不能被继承可以被其他类继承
构造函数没有构造函数的概念可以有构造函数,用于初始化实例
用途通常用于定义包含main方法的单例对象,作为程序的入口点用于定义可以实例化的类型,具有状态和行为
示例object MySingleton { ... }class MyClass { ... }

对象的属性

属性类型描述权限修饰符访问级别
val不可变属性,一旦赋值后不能改变private仅类内部可见
protected类及其子类可见
public所有地方可见(默认)
var可变属性,可以在赋值后改变private仅类内部可见
protected类及其子类可见
public所有地方可见(默认)
隐式属性(通过getter/setter)通过方法定义的属性,Scala鼓励使用这种方式进行属性封装private[包名]仅在指定包内可见
protected[包名]在指定包内的类及其子类可见
无修饰符(默认public)所有地方可见

注意:

  1. 在Scala中,val用于定义不可变属性,而var用于定义可变属性。
  2. 默认情况下,Scala的属性是public的,但可以通过添加适当的访问修饰符来限制其访问级别。注意,Scala中没有public关键字
  3. Scala还提供了包级别的访问修饰符,如private[包名]protected[包名],这些修饰符允许你更精细地控制属性的可见性。
  4. 隐式属性通常是通过getter和setter方法定义的,这是Scala中封装属性的推荐方式。尽管Scala没有显式的语法来定义这些方法,但你可以通过定义带有相同名称的def方法来隐式地创建它们。

示例
注意,Scala中没有public关键字

scala">package com.wunaiieqobject AttributeAccessExample {// 定义一个类,包含不同访问权限的属性class Person(private val id: Int,         // 私有不可变属性private[this] var name: String, // 当前对象私有可变属性(注意:private[this]是Scala特有的,限制为当前对象私有)protected var age: Int,      // 受保护可变属性,子类可访问var email: String     // 公共可变属性) {// 提供一个公共的getter方法来访问私有属性iddef getId: Int = id// 提供一个公共的getter和setter方法来访问当前对象私有属性namedef getName: String = namedef setName(newName: String): Unit = {name = newName}// 由于age是受保护的,它可以在子类中被访问和修改// 这里我们不需要额外的getter和setter方法,除非我们想在类外部以某种方式限制访问// email已经是公共的,所以我们可以直接访问和修改它// 为了演示,我们添加一个方法,该方法会根据年龄打印一条消息def greet(): Unit = {println(s"Hello, my name is $name and I am $age years old. You can reach me at $email.")}}// 定义一个子类,继承自Person类class Employee(id: Int, name: String, age: Int, email: String, val jobId: String) extends Person(id, name, age, email) {// 由于age是受保护的,我们可以在这里访问它def promote(): Unit = {var newAge = age.+(1) // 假设晋升会增加年龄(这只是一个示例,实际情况可能不同)println(s"Employee $name has been promoted. New age: $newAge")}}// 主函数,用于演示如何创建Person和Employee对象,并访问它们的属性def main(args: Array[String]): Unit = {// 创建一个Person对象val person = new Person(1, "Alice", 30, "alice@example.com")// 由于id是私有的,我们需要通过getId方法来访问它println(s"Person ID: ${person.getId}")// 修改name和email属性person.setName("Alice Smith")person.email = "alice.smith@example.com"// 调用greet方法person.greet()// 创建一个Employee对象val employee = new Employee(2, "Bob", 25, "bob@example.com", "ENG001")// 调用promote方法,这将增加员工的年龄employee.promote()// 由于Employee继承自Person,我们可以调用greet方法employee.greet()// 注意:我们不能直接访问employee的private[this] name属性,因为它在当前Employee对象之外是不可见的// 同样,我们也不能直接访问person的受保护属性age,除非我们有一个Person类型的引用并且是在Person类或其子类的上下文中}
}

http://www.ppmy.cn/news/1556635.html

相关文章

华纳云:如何搭建一个简易的文件服务器

搭建一个简易的文件服务器&#xff0c;主要是让多个客户端能够通过网络访问、上传和下载文件。以下是一个基于Linux服务器的文件服务器搭建教程&#xff0c;使用Samba(适用于Windows和Linux客户端)和NFS(适用于Linux客户端)两种常见方法。 一、搭建Samba文件服务器 Samba是一个…

将OBJ或GLB文件转换为3DTiles

格式简介 GLB文件&#xff08;.GLB&#xff09;代表“GL传输格式二进制文件”&#xff0c;是用于共享3D数据的标准化文件格式。确切地说&#xff0c;它可以包含有关三维模型、场景、模型、光源、材质、节点层次和动画的信息。 OBJ文件是一种文本文件格式&#xff0c;这就意味…

linux部分rpm包总结描述

acl-2.2.51-15.el7.x86_64 Commands for Manipulating POSIX&#xff08;可移植操作系统接口 of unix&#xff09; Access Control Lists.有getfacl和setfacl --exclude aic94xx-firmware-30-6.el7.noarch SCSI磁盘阵列驱动 --exlucde aide-0.15.1-13.el7.x86_64 入侵侦察环境 …

现代密码学总结(下篇)

密钥管理与公钥变革 Needham-Schroeder协议 &#xff08;对称&#xff09; 1978年提出, 非安全网络环境下, 借助可信第三方利用对称 密码技术分配会话密钥 假设A和B分别与信任权威T建立了一个共享的静态密钥Kat和Kbt Diffie-Hellman (-Merkle) KE 协议 安全定义: 如果DD…

ARM/Linux嵌入式面经(五四):睿联

一面,技术面,视频面开摄像头。 文章目录 1. 自我介绍。2. 系统调用的流程。系统调用的流程一、系统调用的基本流程二、系统调用的关键组件三、面试官追问及回答3. 虚拟地址到物理地址转换的实现。虚拟地址到物理地址转换的实现实现原理具体步骤面试官追问及答案4. riscv结构的…

【计算机网络安全】网络攻击

实验二 网络攻击 实验人员&#xff1a;第五组全体成员 一、实验目的&#xff1a; 1&#xff1a;掌握ARP欺骗的原理&#xff0c;实践ARP欺骗的过程。 2&#xff1a;掌握TCP劫持的原理&#xff0c;实践TCP劫持的过程。 3&#xff1a;掌握DNS欺骗的原理&#xff0c;实践DN…

jconsole监控c3p0数据库连接数

一、在需要监控的应用服务器所在的机器上&#xff0c;找到应用容器的jvm启动参数&#xff0c;添加如下参数&#xff1a; -Djava.rmi.server.hostname10.127.23.24&#xff1a;当前机器的地址 -Dcom.sun.management.jmxremote.port9999&#xff1a;使用那个端口作为jconsole的…

RK3588 , mpp硬编码rgb, 保存MP4视频文件.

RK3588 , mpp硬编码yuv, 保存MP4视频文件. ⚡️ 传送 ➡️ RK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGBRk3588 FFmpeg 拉流 RTSP, 硬解码转RGBUbuntu x64 架构, 交叉编译aarch64 FFmpeg mppCode Init MppMPP_RET init_mpp