Scala的基础知识点

news/2024/10/6 19:38:49/文章来源:https://www.cnblogs.com/yulugoat/p/18290826

scala特点

Scala介绍

  • Scala是把函数式编程思想和面向对象编程思想结合的一种编程语言
  • 大数据计算引擎Spark由Scala编写

Scala特点

  • 多范式
    • 面向对象
    • 函数式编程
  • 兼容JAVA
    • 类库调用
    • 互操作
  • 语法简洁
    • 代码行短
    • 类型推断
    • 抽象控制
  • 静态类型化
    • 可检验
    • 安全重构
  • 支持并发控制
    • 强计算能力
    • 自定义其他控制结构

scala基础编程

scala的第一个代码 hello world

注意事项:

  • 如果一个scala文件想要运行,class要改成object
  • 如果是class,就仅单纯代表一个类,如果是object代表的是单例对象
  • scala语法中,一句话结束不需要加分号
  • scala文件中,可以使用java中的类和方法
object HelloWorld {def main(args: Array[String]): Unit = {println("hello world!")System.out.println("hello world!!!")}
}

初学scala

  • 变量:在程序的运行过程中,其值可以发生改变的

  • 在scala中定义一个变量,需要使用一个关键字:var

  • 注意:

    1、变量一旦定义,它的类型就确定,可以不用手动指定类型,根据赋的值自动推断出类型

    2、也可以手动的指定变量的数据类型,完整的写法:var 变量名:数据类型 = 值

scala和java中类型关系对应:

java: scala:

byte Byte

short Short

int Int

long Long

float Float

double Double

boolean Boolean

char Char

定义常量:在程序的运行过程中,其值不能发生改变的量

在scala中定义一个常量,需要使用一个关键词:val

scala中字符串的使用

字符串:由若干个字符组成的序列

在scala中字符串是如何做拼接的?

  • 使用+号拼接 这种拼接方式比较消耗性能
  • 使用StringBuilder
  • 前提:有一组序列,使用scala特有的函数 mkString
  • 使用scala特有的字符串传递方式s"${变量}"底层就是使用StringBuilder

scalaIO流

读取一个文件

1、可以使用java的方式读取一个文件

def main(args: Array[String]): Unit = {// 使用java的方式读取val br: BufferedReader = new BufferedReader(new FileReader("scala/data/demo"))var line:String = br.readLine()while (line != null){println(line)line = br.readLine()}
}

2、使用scala中的读取文件

 val bs: BufferedSource = Source.fromFile("scala/data/demo.txt")val strings: Iterator[String] = bs.getLines()while (strings.hasNext){val str: String = strings.next()println(str)}
  • 注意:Source.fromFil 底层是使用了字节输入流读取数据FileInputStream

scala读取文件简写

    for (e <- bs.getLines()){println(e)}

3、使用java方法写文件

    val bw: BufferedWriter = new BufferedWriter(new FileWriter("scala/data/text.txt"))bw.write("杰克爱是越南战俘!!")bw.newLine()bw.write("小手也是!!")bw.flush()bw.close()

4、scala里面没有写文件的方式!!!

scala异常Exception

scala中的异常和java中的很像

可以手动抛出异常

import java.io.{BufferedReader, FileReader}
import java.util.Scannerobject ExceptionDemo {
def main(args: Array[String]): Unit = {try {println(10/2)val arr: Array[Int] = Array(11, 22, 33, 44, 55)
//      println(arr(5))// 手动抛出异常var sc:Scanner = new Scanner(System.in)val reader: BufferedReader = new BufferedReader(new FileReader("scala/data/demo1.txt"))println("输入除数:")var num:Int = sc.nextInt()if(num != 0){println(10/num)}else{throw new ArithmeticException("您输入的除数是0!!!")}}catch{case e:ArithmeticException =>
//        println("除0异常")e.printStackTrace()case e:ArrayIndexOutOfBoundsException =>e.printStackTrace()case _ =>println("出现了异常")}finally {println("finally代码块")}println("hi nihao haha e")
}
}

scala函数

def:定义函数或者方法的关键字

main:是函数或者方法的名字,符合标识符的命名规则

args:函数形参的名字

Array[String]:参数的数据类型是一个元素为字符串的数组

Unit:等于java中的void viod表示无返回值的意思

=:后面跟着函数体

在不同的地方定义,称呼不一样

函数:在object中定义的叫做函数

方法:在class中定义的叫做方法

def main(args: Array[String]): Unit = {}

函数的定义格式

// 定义格式一:如果函数有返回值,且最后一句话有返回值的话,return可以不写
def add1(a1: Int, b1: Int): Int = {a1 + b1
}
// 定义格式二:如果函数体中只有一句话那么大括号也可以不写
def add2(a1: Int, b1: Int): Int = a1 + b1
//定义格式三:如果函数没有参数的时候,小括号也可以不写
def show = println("他是铁头功!我是金刚腿!")
}

scala中的函数可以嵌套定义,函数中可以再定义函数

但是调用必须在定义之后

 def plus(x:Int,y:Int):Int = {x + y}val sum3: Int = plus(20, 20)println(sum3)

注意:

  • 函数或方法的定义必须定义在class或者object中

创建类用来调用方法

class Demo1{
// 这里叫方法,将来调用时需要创建该类的对象才可以调用
def add(a:Int,b:Int):Int = {a + b
}
}// 调用类中的方法val demo = new Demo1()val sum4: Int = demo.add(1, 2)println(sum4)

通过类名调用函数

 //object中的函数可以使用类名调用,类似于静态一样val res1: Int = Demo5Function.add2(200, 100)println(res1)//object调用形式二:object中的函数调用时,可以省略类名// 如果方法调用的函数只有一个参数的时候,可以将.和小括号用空格代替调用val res2: Int = Demo5Function fun1 "1000"println(res2)

函数递归

object Demo6Function {
def main(args: Array[String]): Unit = {/*** 递归方法定义时要有出口,不然就是死递归*/val res1: Int = factorial(5)println(s"5的阶乘是:$res1")println(s"5的阶乘是${Demo6Function factorial 5}")}def factorial(num:Int):Int = {if(num == 1){1}else{num * factorial(num -1)}}
}

class

可以在scala程序中定义类

类:构造方法 成员方法 成员变量

构造方法:

1、在scala中构造方法的编写和在java中的不太一样。类所拥有的大括号中都是构造代码块的内容

2、默认情况下,每一个类都应该提供一个无参的构造方法

3、构造方法可以有许多

创建两个类一个有参,一个无参

class Student(name: String, age: Int) {
/*** 定义成员变量*/val _name: String = nameval _age: Int = agevar _gender: String = _ //下划线表示将来会赋予默认值//构造方法可以写很多个def this(name: String, age: Int,gender:String) {this(name:String,age:Int)_gender = gender}// 重写toString方法override def toString:String = {"姓名:"+_name+", 年纪:"+_age+",性别:"+_gender}
}
class Student2{def fun1(): Any= {println("杰克爱会赢的!")}
}

创建main函数调用类中的方法

  def main(args: Array[String]): Unit = {val s1: Student = new Student("Real-person", 18, "女")println(s1)// 如果调用的是一个类的无参构造方法,new的时候小括号可以不用写val s2: Student2 = new Student2s2.fun1()val s3:Object= new Student("five-piece",30,"男")println(s3.toString)}

样例类

scala提供了一个非常好用的功能:样例类

较少用户创建类所编写代码量,只需要定义成员变量即可,自动扩充成员变量,构造方法,重写toString方法

  • 样例类中的成员变量,编译后默认是被jvm添加了final关键字,用户是改变不了的
  • 对于scala来说,默认是被val修饰的
  • 如果将来想要被改变,定义的时候需要使用var进行修饰

创建样例类

case class Teacher(name:String,age:Int, var like:String)
  def main(args: Array[String]): Unit = {val t1: Teacher = new Teacher("teacher.lee", 16, "study")println(t1)t1.like = "watchingTV"println(t1.like)

apply

创建一个Object对象时可以直接调用里面的函数

object Demo9Apply {
def main(args: Array[String]): Unit = {Book()
}
}object Book{
def apply():Unit = {println("你的牌打的也忒好了!!")
}
}

当Object名与class名一样是叫做伴生对象

object Demo9Apply {
def main(args: Array[String]): Unit = {val book: Book = Book("我的奋斗", 99)println(book)
}
}object Book{
def apply(name:String,price:Int):Book = {new Book(name, price)
}
}class Book(name:String,price:Int){
var _name:String = name
var _price:Int = priceoverride def toString: String = "书名:" + _name + ", 价格:" + _price
}

Scala中的函数式编程

面向对象编程:将对象当作参数一样传来传去

1、对象可以当作方法参数传递

2、对象也可以当作方法的返回值返回

3、当看到类、抽象类,接口的时候,今后无论是参数类型还是返回值类型,都需要提供对应的实现类对象

面向函数式编程:将函数当作参数一样传来传去

1、函数A当作函数B的参数进行传递

2、函数A当作函数B的返回值返回

在scala中,将函数也当作一个对象,对象就有类型

函数在scala也有类型的说法

参数类型 => 返回值类型

  1. 一个参数为字符串类型,返回值是整数类型的函数

        def fun1(s:String):Int = {s.toInt + 1000}val res1: Int = fun1("100")
    
  2. 定义变量的方式,定义一个函数,将函数当作对象,赋值给类型是函数类型的变量,将来可以直接通过变量调用函数

        val fun2: String => Int = fun1val res2: Int = fun2("200")println(res2)
    
  3. 函数A作为函数B的参数定义,本质上讲函数A的处理逻辑主体传给了函数B,在函数B中使用这个处理逻辑

        //定义def fun3(f:String => Int):Int = {val a1: Int = f("1000")a1 + 300}def show1(s:String):Int={s.toInt}def show2(s:String):Int={s.toInt + 11111}//调用val res3: Int = fun3(show1)println(res3)val res4: Int = fun3(show2)println(res4)
    
  4. 定义一个函数,函数的参数列表中,既有正常的类型参数,也有函数类型的参数

        def fun4(s:String,f:String=>Int):Int={val a1: Int = f(s)a1 + 1000}def show3(s:String):Int={s.toInt}def show4(s: String): Int = {s.toInt + 1000}val res5: Int = fun4("2000", show4)println(res5)
    

    使用lambda表达式改写函数作为参数传递的调用形式

        val r1: Int = fun4("2000", (s: String) => s.toInt)val r2: Int = fun4("2000", (s: String) => s.toInt + 1000)//在scala中,数据类型可以自动类型推断val r3: Int = fun4("2000", s => s.toInt)//如果当作参数的函数的参数只在函数主体使用了一次,那么可以使用_代替val r4: Int = fun4("2000", _.toInt + 1000)println(r1+"|"+r2+"|"+r3+"|"+r4)
  5. 函数当作参数传递的应用

      def main(args: Array[String]): Unit = {val arr: Array[Int] = Array(11, 22, 33, 44, 55)//    for(e<-arr){//      println(e)//    }def fun1(i: Int): Unit ={println(i*2)}//def foreach[U](f: A => U): Unit//foreach函数需要一个参数和数组元素一样类型的类型,返回值是Unit的函数//foreach函数的主要作用是将调用该方法的序列中的元素,依次取出传递给后面的函数进行处理arr.foreach(fun1)println("*" * 50)//scala自带的一个函数// def println(x:Any) = Console.println(x)//Any可以接受任意的数据类型元素arr.foreach(println)}
    
  6. 函数当返回值返回

    1. 参数是String类型,返回值是一个函数(参数值是String类型,返回值是Int)
    2. 方式2这种将参数分开定义,今后调用可以分开传递,这种做法,在scala中叫做函数柯里化
    3. 偏函数的使用
      def main(args: Array[String]): Unit = {def fun1(s1: String): String => Int = {def show(s: String): Int = {s.toInt + s1.toInt}show}val resFun1: String => Int = fun1("1")val res1: Int = resFun1("1000")println(res1)def fun2(s1:String)(s:String):Int = {s.toInt+ s1.toInt}val res2: Int = fun2("1")("1000")println(res2)// 偏函数调用def function1(s1:String,s2:String):Int={s1.toInt+s2.toInt}val f1: String => Int = function1("1", _)val res3: Int = f1("1000")val res4: Int = f1("2000")val res5: Int = f1("3000")println(s"res3:$res3,res4$res4,res5$res5")}
    

    柯里化:

    • 本身是一个数学界的名词,本意是原来一次传递多个参数,现在被改变成了可以分开传递的形式,这种做法叫做柯里化
    • 在scala中体现柯里化,指的是函数的返回值也是一个函数,将来调用时参数可以分开传递
    • 提高了程序的灵活性和代码的复用性
    • 在Scala中也可以通过偏函数实现参数分开传递的功能

scala中的集合

scala中的集合:

  • List:元素有序,且可以发生重复,长度固定的
  • Set:元素无序,且唯一,长度固定的
  • Map:元素是键值对的形式,键是唯一的
  • Tuple:元组,长度是固定的,每个元素的数据类型可以不一样

arraylist

在utiljava包下的集合

object Demo13ArrayList {
def main(args: Array[String]): Unit = {val list1: util.ArrayList[Int] = new util.ArrayList[Int]()list1.add(11)list1.add(22)list1.add(33)list1.add(44)list1.add(55)println(list1)println("*" * 50)var i: Int = 0while (i < list1.size()) {println(list1.get(i))i += 1}
}

注意: scala中的for循环只能遍历scala中的序列,无法遍历java中的序列

List

  • 可以创建一个空的集合

  • 使用size或length函数获取List集合的长度

  • 可以直接通过索引下标获取元素

  • scala推荐获取第一个元素的方式是调用head函数

  • 可以根据指定的分隔符拼接元素

  • reverse函数反转,返回一个新的集合

  • distinict函数去重,返回一个新的集合

  • tail函数去除第一个元素,其余的元素返回一个新的集合

  • take(n)函数从左向右取元素,取若干个

  • takeRight(n)函数 取右边,组成新的集合

  • takewhile(条件表达式) 从第一个判断取数据,直到不符合条件停止

  • sum函数 元素必须是数值

List高阶函数

foreach:将集合中的元素依次取出传入到后面的函数中

注意:foreach函数是没有返回值的,要么就输出,要么就其他的方式处理掉的

map:依次处理每一个元素,得到一个新的结果,返回到一个新的集合中

filter:保留符合条件的元素

sortBy:根据条件排序

sortWith:两个数之间的关系排序

flatMap:扁平化

groupBy:根据条件分组

Set

scala中的Set集合也是不可变的,除了排序相关的函数以外,List集合有的高阶函数,Set集合也有

set 和list可以相互转换

    val set1: Set[Int] = Set(1, 4, 3, 6, 5)val set2: Set[Int] = Set(3, 6, 5, 7, 8)// 求交集val set3: Set[Int] = set1 & set2println(s"set1:${set1}")println(s"set2:${set2}")println(s"set3:${set3}")println("*" * 50)// 求并集val set4: Set[Int] = set1 | set2println(s"set1:${set1}")println(s"set2:${set2}")println(s"set4:${set4}")println("*" * 50)//求差集val set5: Set[Int] = set1 &~ set2println(s"set1:${set1}")println(s"set2:${set2}")println(s"set5:${set5}")println("*" * 50)//Set集合和List集合相互转换// list to setval list1: List[Int] = List(11, 22, 33, 44, 55, 11, 22, 44, 88, 33, 44, 99, 11, 22, 55)val resSet1: Set[Int] = list1.toSetprintln(s"list1:${list1}")println(s"resSet1:${resSet1}")println("*" * 50)//set to listval resList1: List[Int] = resSet1.toListprintln(s"list1:${list1}")println(s"resSet1:${resSet1}")println(s"resList1:${resList1}")

Mutable

注意导包:通过观察api发现,不可变的集合是属于scala.collection.immutable包下的

如果将来想要使用可变的集合,就要去scala.collection.mutable包下寻找

普通list集合的中函数在可变list集合都可以调用

 
def main(args: Array[String]): Unit = {// 定义一个可变的list集合val listBuffer = new ListBuffer[Int]println(listBuffer)listBuffer.+=(11)listBuffer.+=(22)listBuffer.+=(33)listBuffer.+=(11)listBuffer.+=(55)listBuffer.+=(22)listBuffer.+=(33)listBuffer.+=(66)println(listBuffer)println("*" * 80)// 获取元素println(listBuffer(2))println(listBuffer.head)println(listBuffer.last)// 删除元素listBuffer.-=(33)println(listBuffer)println("*" * 80)//批量添加元素listBuffer.+=(100,200,300,400)println(listBuffer)println("*" * 80)val list: List[Int] = List(99, 88, 77)listBuffer.++=(list)println(list)println("*" * 80)/*可变的Set集合*/val hashSet = new mutable.HashSet[Int]()val resSet: hashSet.type = hashSet.+=(123, 456, 789)println(resSet)}

tuple

大小,值是固定的,根据创建的类来定,每个元素的数据类型可以是不一样的,最高可以创建存储22个元素的元组

object Demo17Tuple {def main(args: Array[String]): Unit = {val tuple1: (Int, String, Int, String, String) = Tuple5(1001, "jack爱", 18, "男", "用黑人牙膏")println(tuple1)val s2 = new Student3("zobayan", 4, "helicopter")val tuple: (Int, Student3) = Tuple2(1002, s2)println(tuple._2.like)}}case class Student3(name:String,age:Int,like:String)

Map

	val map1: Map[Int, String] = Map((1001, "张三"), (1002, "李四"), (1003, "王五")		(1001, "赵六"), 1005 -> "易政")println(map1)//键是唯一的,当键一样的时候值会覆盖println("*" * 80)//苦于根据键获取值// 小括号获取值 当键不存在的时候会报错println(map1(1002))// 使用get获取值 当键不存在时不会报错 返回Noneprintln(map1.get(1002))// 根据键获取值,当键不存在时,返回所提供的默认值,提供的默认值苦于是任何类型的数据println(map1.getOrElse(1001, 0))println("*" * 80)//获取所有的键组成一个迭代器val keys: Iterable[Int] = map1.keyskeys.foreach(println)println("*" * 80)//获取所有的值组成一个迭代器val values: Iterable[String] = map1.valuesvalues.foreach(println)println("*" * 80)// 遍历集合的第一种方式,先获取所有的键在根据键获取对应的值val keys1: Iterable[Int] = map1.keysfor (e <- keys1) {val value: Any = map1.getOrElse(e, 0)println(s"键:$e,值:$value")}println("*" * 80)//遍历集合的第二种方式,直接遍历map集合,得到每一个由键值对组成的元组for (kv <- map1) {println(s"键:${kv._1},值:${kv._2}")}println("*" * 80)// 遍历集合的第三种方式,foreach的方式map1.foreach((kv: (Int, String)) => println(s"键:${kv._1},值:${kv._2}") )

综合小练习:根据上述所讲内容完成数字统计

hello|world
java|hadoop|linux
java|scala|hadoop
hive|java|hello|world
hello|world
java|hadoop|linux
java|scala|hadoop
hive|java|hello|world
hello|world
java|hadoop|linux
java|scala|hadoop
hive|java|hello|world
java|hadoop|linux
java|scala|hadoop
hive|java|hello|world
hello|world
java|hadoop|linux
  def main(args: Array[String]): Unit = {val lineList: List[String] = Source.fromFile("scala/data/words.txt").getLines().toListval newLineList: List[String] = lineList.flatMap(line => line.split("\\|"))val wordMap: Map[String, List[String]] = newLineList.groupBy(e => e)val wordList: List[(String, Int)] = wordMap.map { word =>(word._1, word._2.size)}.toListwordList.foreach { word =>println(s"${word._1}:${word._2}")}wC()}// 链式编程简写private def wC(): Unit = {Source.fromFile("scala/data/words.txt").getLines().toList.flatMap(_.split("\\|")).groupBy(e => e).map { word => (word._1, word._2.size) }.toList.foreach { word => println(s"${word._1}:${word._2}") }}

scala其他常用知识点

JDBC

JDBC的连接步骤:

  • 1、注册驱动
  • 2、创建数据库连接对象
  • 3、创建数据操作对象
  • 4、执行sql语句
  • 5、如果第四步是查询的话,分析查询结果
  • 6、释放资源

Json文件处理

{"flag": "SUCCESS","student_list": [{"id": "1001","name": "易政","age": 18,"like": ["学习","看美女","打游戏"]},{"id": "1002","name": "小虎","age": 19,"like": ["踢足球","打联盟","睡觉"]}]
}
  def main(args: Array[String]): Unit = {val lineList: List[String] = Source.fromFile("scala/data/stu.json").getLines().toListval jsonStr: String = lineList.mkString("\r\n")// 使用fastjson中的JSON类,将一个字符串转成一个json对象// 转成json对象之后可以通过键获取值//parseObject将整体转换成一个json格式数据val jsonObject: JSONObject = JSON.parseObject(jsonStr)val s1: String = jsonObject.getString("student_list")// parseArray将一个"[{},{}]"变成一个元素是json对象的数组val jSONArray: JSONArray = JSON.parseArray(s1)var i:Int = 0while (i<jSONArray.size()){val obj1: JSONObject = jSONArray.getJSONObject(i)val name: String = obj1.getString("name")val like: String = obj1.getString("like")println(s"姓名:$name,兴趣:$like")i += 1}}

Scala和java的相互转换

将java中的集合转成scala中的集合,java中的集合本来是没有转换scala的功能,需要导入隐式转,scala中的导包,可以在任意地方

  def main(args: Array[String]): Unit = {// 创建一个java中的集合val array1 = new util.ArrayList[Int]()array1.add(11)array1.add(22)array1.add(33)array1.add(66)array1.add(55)array1.add(44)println(array1)/*TODO将java中的集合转成scala中的集合java中的集合本来是没有转换scala的功能,需要导入隐式转换scala中的导包,可以在任意地方*/import scala.collection.JavaConverters._val list1: List[Int] = array1.asScala.toListprintln(list1)val javaList: util.List[Int] = list1.asJavaprintln(javaList)}

Macth模式匹配

语法:

语法:表达式 match{case 值|[变量名:类型]|元组|数组|对象 =>匹配成功执行的语句case xxx => xxxcase _ xxx => xxx}

若模式匹配没有对应的匹配,会报错!!!

案例:

  def main(args: Array[String]): Unit = {// 匹配变量值var i: Int = 200i match {case 20 => println("该值是20")case 200 => println("该值是200")case _ => println("该值是200")}// 可以匹配数据类型var flag: Int = 200flag match {case _: Int => println("是Int类型")case _ => println("是Boolean类型")}//匹配元组val tuple1: (Int, String, Int) = Tuple3(1001, "张三", 18)tuple1 match {case (a1: Int, a2: String, a3: Int) =>println(s"学号:$a1,姓名:$a2,年龄:$a3")}//模式匹配的应用:避免异常val map1: Map[Int, String] = Map((1001, "张三"), (1002, "李四"))val sc: Scanner = new Scanner(System.in)println("请输入你想要想查询的键:")val key: Int = sc.nextInt()map1.get(key) match {case Some(a:Any) =>println(s"${key}键对应的值为$a")case None =>println(s"${key}键对应的值不存在!")}println("*" * 80)val stuList: List[String] = Source.fromFile("scala/data/students.txt").getLines().toListval stuArrayList: List[Array[String]] = stuList.map((line: String) => line.split(","))stuArrayList.map {case Array(id: String, name: String, gender: String, age: String, clazz: String) =>(id,name,age,ger,clazz)}.foreach(println)}

implicit 隐式转换

  1. 隐式转换函数

    // 定义隐式转换函数
    // 在需要返回值类型的功能的时候,自动地根据已有隐式转换函数将参数的类型转成返回值的类型implicit def implicitFun1(str: String): Int = {return Integer.parseInt(str)}implicit def implicitFun2(str: String): Int = {return Integer.parseInt(str) + 200}def fun1(s: Int): Int = {return s + 100}println(fun1(100))println(fun1("200"))
    
  2. 隐式转换类

    注意:implicit使用的地方,不能超过object作用域

      def main(args: Array[String]): Unit = {//    val demo1 = new Demo12("scala/data/students.txt")//    val lineList: List[String] = demo1.show1()//传入字符串时会自动匹配成为一个Demo12的对象,可以调用对象里面的方法val lineList1: List[String] = "scala/data/students.txt".show1()val lineList2: List[String] = "scala/data/score.txt".show1()"jackeylove".f()}implicit class Demo12(path: String) {def show1(): List[String] = {Source.fromFile(path).getLines().toList}def f(): Unit = {println(s"找到一个越南战俘${path}")}}
    
  3. 隐式转换变量

      def main(args: Array[String]): Unit = {//定义一个隐式转换参数def fun1(a1: Int)(implicit a2: Int): Int = a1 + a2// 定义一个隐式转换变量implicit var i1:Int = 100val i: Int = fun1(200)println(i) // 在没有定义隐式转换时,必须要穿两个数字不然返回的是一个函数 会报错}
    
  4. 隐式转换的重要知识点(面试题)

    scala中的隐式转换知道吗?请介绍一下。

    • scala中的隐式转换,本质上就是将一个类型转换成另一个类型去使用另一个类型中的功能
    • scala中的隐式转换分为3种:隐式转换函数、隐式转换类、隐式转换变量
    • 隐式转换函数,在使用隐式转换函数返回值类型的功能的时候,可以自动的将参数的类型转成返回值类型进行使用
    • 隐式转换类,可以自动的将构造方法的参数类型转成类的类型,将来可以直接使用构造方法中的类型调用类中的方法
    • 隐式转换变量,配合函数定义中的隐式转换参数使用,将来调用函数的是,可以不用传入隐式转换参数的值,自动使用对应类型的隐式转换变量,当然也可以手动传入具体的值给隐式转换参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/740819.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

相机的标定

Camera-calibration 用于矫正相机的畸变代码部分 #打开摄像头,将读取的视频保存在本地,名字叫output.avi# coding=utf-8 import cv2 as cv cap = cv.VideoCapture(0) # 检查是否成功打开摄像头 if not cap.isOpened():print("Cannot open camera")exit() # 获取摄像…

关于golang函数传参问题

今天在写leetcode的一个简单问题的时候发现golang的切片传递并不是直接 传递地址的,而是一个地址副本。如图所示,当我利用test函数对nums1和nums2数组处理时,并不是对原来的nums1和nums2做处理,而是对他们的副本nums1_temp和nums2_temp做处理,但是nums1_temp和nums1都指向…

PN转Modbus RTU模块连接ACS4QQ变频器通信

巴图自动化PN转Modbus RTU模块(BT-MDPN10)的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。PN转Modbus RTU模块集成了Modbus和Profinet两种协议,支持Modbus RTU主从站,可连接变频器、智能高低压电器、功率测量设备等RS485/232接口设备。一台完整的机器在出厂前由…

RS232转PN协议网关模块连接PLC和霍尼韦尔条码扫描器通信

利用RS232转PN协议网关(BT-PNR20)模块连接PLC与条码扫描器,通过配置RS232转PN协议网关(BT-PNR20)模块连接PLC与条码扫描器参数实现高效通信,提高生产效率,降低人工干预成本。涉及设备准备、硬件连接、配置步骤和监控设置。为了更快地输入信息,许多设备都配备了条码扫描…

vscode 远程连接 Ubuntu (SSH)

vscode ssh Ubuntu 流程及一些常见问题的解决安装对应的拓展包显示所有的命令(Ctrl+Shift+p)获取虚拟机的ip sudo apt install net-tools ifconfig进行连接如果连接的时候报错(管道不存在) 在Ubuntu中打开ssh服务即可如果连接了很久没有连上(Permission denied (publickey…

2024已过半,还没试过在vue3中使用ioc容器吗?

Zova 是一款支持 IOC 容器的 Vue3 框架。有了 IOC 容器的加持,定义响应式状态不再需要ref/reactive,也不再需要ref.valueVue3 已经非常强大和灵活了,为什么还要引入 IOC 容器呢?IOC 容器离不开 Class,那么我们就从 Class 谈起 Class的应用场景 一提起 Class,大家一定会想…

cpp查错误

使用Windows事件查看器调试崩溃 https://www.cnblogs.com/yilang/p/11993912.html1、2、生成.map看函数地址 3、map里找不到0xc0000409 4、 搜 异常代码 0xc0000409 5、堆栈设置

Vue3 如何接入 i18n 实现国际化多语言

如何在现有 Vue 3.0 + Vite 项目中,引入 i18n 实现国际化多语言,可以手动切换,SEO友好,且完整可用的解决方案。1. 基本方法 在 Vue.js 3 中实现网页的国际化多语言,最常用的包是 vue-i18n,通常我们会与 vue-i18n-routing 一起使用。 vue-i18n 负责根据当前页面的语言渲染…

【安全运营】企业钓鱼演练实践

一、 群智集锦 问:请教各位师傅个问题,你们多长时间做一次钓鱼演练?答:全员型的半年一次,小范围的一个季度一次;答:我们内部每月都有做钓鱼演练,主要针对新员工,钓鱼主题一般不改变,针对全员的时候会换一下套路;问:请教个问题,大家进行钓鱼演练统计是怎么统计展示…

植物大战僵尸 杂交版

下载地址:https://download.csdn.net/download/hello_hlqk/89525708?spm=1001.2101.3001.9500 植物大战僵尸杂交版是一款由B站UP主 @潜艇伟伟迷 基于原版植物大战僵尸魔改的塔防类游戏。这款游戏在保留原有游戏精髓的基础上,进行了大胆的创新和尝试。UP主将不同的植物进行了…

Modbus转Profibus模块连SmartPLC接汇川630伺服案例

Modbus转Profibus模块(XD-MDPB100)是一种通讯协议转换器,能够实现Modbus 协议与Profibus-DP协议的信息共享。汇川630伺服作为一种先进的运动控制设备,其平稳性和准确性获得了充分肯定。本文将详细分析怎么使用Profibus转Modbus模块(XD-MDPB100)连接SmartPLC以及配备汇川630…

6.20+rand()%10~7.8

集训、集训、集训忘了放假之前的事了 首先排除是因为点分治调破防了 (发现一写数据结构专题闲话就变月记了) 其实还有原因是每次写这东西到一半就会因为点睡眠就会不小心点成关机所以似了 换校区(放假) 说实话放的还挺久的 在衡水住的酒店,打了一下午崩铁 速成了一下超击破…