Scala面试
Scala声明变量推荐使用val
Scala是一种强类型语言,使用前变量的类型必须确定,编译器将语法补全,代码可以简化
能推断出变量的类型,那么这个类型可以省略
Java中变量的初始化可以在执行前完成,不需要必须在声明时完成
Scala在声明变量的同时需要初始化变量
1. Scala开发环境搭建
2. 变量和数据类型
(1) 掌握var和val的区别
可变变量使用关键字var 进行声明 值可以发生变化
object ScalaVariable {
def main( args: Array[ String ] ) : Unit = {
var username : String = "zhangsan"
username = "lisi"
username = true
}
}
不可变变量使用关键字val 进行声明, 类似于Java语言中的final 关键字, 不可变化, 不等同于常量, 实际上还是变量
object ScalaVariable {
def main( args: Array[ String ] ) : Unit = {
val username : String = "zhangsan"
username = "lisi"
username = true
}
}
补充: 常量也称为字面量, 常量的计算在百年有意识就已经完成了
(2)掌握数据类型(Byte Short Int Long Float Double Char Boolean )之间的转换关系
Any
AnyVal
浮点型
Double
64 位,双精度浮点数
Float
32 位,单精度浮点数
整型
Long
64 位
Int
32 位,- 21 E~ 21 E
Short
16 位,- 3 W2~ 3 W2
Byte
8 位,- 128 到127
Boolean
Char
StringOps
Unit
表示无值,和其他语言中的void等同,只有一个实例( )
AnyRef
Scala collections
all java classes
Other Scala classes
备注:Null为所以引用对象的子类,只有一个实例null
备注
Nothing 是所有类型的子类
类型转换:
规则
小转大,自动转
大转小,需强转
自动类型转换(implicit conversion)
细节:
多种类型混合运算时,自动将所有数据转为最大的
( byte, short) 和 char之间不会相互自动转换
强制类型转换
用法
. toXxx
scala是完全面向对象的语言,所有的类型都提供了toString方法,可以直接转换为字符串
lon. toString
val i = 10
val s = "hello " + i
3. 流程控制
if-else
if ( 布尔表达式) {
}
if ( 布尔表达式) {
} else {
}
object ScalaBranch {
def main( args: Array[ String ] ) : Unit = {
val age = 30
val result = if ( age < 18 ) {
"童年"
} else if ( age <= 30 ) {
"青年"
} else if ( age <= 50 ) {
"中年"
} else {
"老年"
}
println( result)
}
}
for
for ( 循环变量 <- 数据集 ) {
循环体
}
while
while ( 循环条件表达式 ) {
循环体
}
do {
循环体
} while ( 循环条件表达式 )
break与continue
scala是完全面向对象的语言,所以无法使用break,continue关键字这样的方式来中断,或继续循环逻辑,而是采用了函数式编程的方式代替了循环语法中的break和continue
object ScalaLoop {
def main( args: Array[ String ] ) : Unit = {
scala. util. control. Breaks. breakable {
for ( i <- 1 to 5 ) {
if ( i == 3 ) {
scala. util. control. Breaks. break
}
println( i)
}
}
}
}
补充: 九层妖塔练习
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * * *
for ( i<- 0 to 8 ) {
Print( “ ”* ( 8 - i) + “* ” * ( 2 * i+ 1 ) )
}
4. 函数式编程
1. 面向对象( 个体) , 将个体的特性抽取出来为类, 静态的和对象无关, Object模拟静态语法, 为对象
Java可以用反射封装框架
函数: function( 功能) , 考虑的时封装, 重复使用
可以嵌套封装
方法也是函数, 但函数不是方法
方法声明在类中, 类中声明的函数就是方法
函数可以声明在任何地方, 函数的声明等同于方法的声明
方法中可以声明函数, 函数中不能声明方法
2. 基本语法:
[ 修饰符] def 函数名 ( 参数列表 ) [ : 返回值类型] = {
函数体
}
private def test( s : String ) : Unit = {
println( s)
}
在编译时, Scala采用的是私有静态方法来声明, 函数是有作用域的, Scala会将函数的名称进行修改, 方法名不修改, 避免冲突
Scala中的函数不能重载, 在同一个作用域中, 相同名称的函数只能有一个
3. 至简原则: 能省则省
( 1 ) 省略return 关键字
def f2( name : String ) : String = {
"Name :" + name
}
( 2 ) 省略花括号
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun2( ) : String = "zhangsan"
}
}
( 3 ) 省略返回值类型
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun3( ) = "zhangsan"
}
}
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun5( ) : String = {
return "zhangsan"
}
println( fun5( ) )
}
}
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun5( ) : Unit = {
return "zhangsan"
}
println( fun5( ) )
}
}
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun5( ) {
return "zhangsan"
}
println( fun5( ) )
}
}
( 4 ) 省略参数列表
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun4 = "zhangsan"
fun4
fun4( )
}
}
( 5 ) 省略等号
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun5( ) {
return "zhangsan"
}
println( fun5( ) )
}
}
( 6 ) 省略名称和关键字
( ) -> { println( "xxxxxxxx" ) }
( 7 ) 匿名函数
val f9 = ( i : Int ) => { println( "xxxxx" ) }
4. 高阶函数
将函数当成一个类型来使用
( 1 ) 函数作为值
object ScalaFunction {
def text( ) : Unit = {
}
val f = text
val f1 = text _
val f2 : ( ) => Unit = text
}
}
( 2 ) 将函数作为参数
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun2( i: Int ) : Int = {
i * 2
}
def fun22( f : Int => Int ) : Int = {
f( 10 )
}
println( fun22( fun2) )
}
}
( 3 ) 函数作为返回值
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def text3( ) : Unit = {
println( "zzz" )
}
def fun1( ) : ( ) => Unit = {
text3
}
fun1( ) ( )
def outer( x: Int ) = {
def middel( y: Int ) = {
def inner( f: ( Int , Int ) => Int ) = {
f( x, y)
}
inner _
}
middel _
}
outer( 10 ) ( 20 ) ( ( x: Int , y: Int ) => { x+ y} )
println( outer( 10 ) ( 20 ) ( _ + _) )
outer( 10 ) ( 20 ) ( ( x: Int , y: Int ) => {
x * y
} )
println( outer( 10 ) ( 20 ) ( _ * _) )
}
}
( 4 ) 匿名函数
( 5 ) 将函数作为对象
def text4( ) : Unit = {
println( "zzzz" )
}
def fun2( ) = {
text4 _
}
fun2( ) ( )
( 6 ) 控制抽象
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun7( op: => Unit ) = {
op
}
fun7{
println( "xx" )
}
}
}
( 7 ) 闭包
如果函数中使用外部变量,为了防止变量数据丢失,将变量包含到函数的内部,形 成闭合的效果,形成闭包,改变变量的生命周期
闭包就是一个函数和与其相关的引用环境(变量/ 值)组合的一个整体( 实体) 。
def outer1( x: Int ) = {
def inner( y: Int ) = {
x+ y
}
inner _
}
val r = outer1( 10 )
println( r( 20 ) )
( 8 ) 函数柯里化
( 9 ) 递归函数
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun8( j: Int ) : Int = {
if ( j <= 1 ) {
1
} else {
j * fun8( j- 1 )
}
}
println( fun8( 5 ) )
}
}
( 10 ) 惰性函数
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun9( ) : String = {
println( "function..." )
"zhangsan"
}
lazy val a = fun9( )
println( "----------" )
println( a)
}
}
5. 匿名函数
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun4( f: Int => Int ) : Int = {
f( 10 )
}
println( fun4( ( x: Int ) => { x * 20 } ) )
println( fun4( ( x) => { x * 20 } ) )
println( fun4( ( x) => x * 20 ) )
println( fun4( x=> x * 20 ) )
println( fun4( _ * 20 ) )
}
}
6. 函数柯里化
柯里化指的是将原来接受多个参数的函数变成新的接受一个参数的函数的过程,
新函数的参数接受原来的第二个参数为唯一参数
如果有n个参数, 就是把这个函数分解成n个新函数的过程
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun6( i: Int ) ( j: Int ) = {
i * j
}
}
}
7. 函数参数
object ScalaFunction {
def main( args: Array[ String ] ) : Unit = {
def fun2( i: Int ) : Int = {
i * 2
}
def fun22( f : Int => Int ) : Int = {
f( 10 )
}
println( fun22( fun2) )
}
}
5. 面向对象
(1)Scala与Java继承方面的区别
继承
实例
isInstanceOf 判断对象是否为指定类的对象
asInstanceOf 将对象转换为指定类型
classOf 精确的获取类
子类与父类
类有一个主构器和任意数量的辅助构造器,而每个辅助构造器都必须先调用主构造器( 也可以是间接调用)
只有主构造器可以调用父类的构造器。辅助构造器不能直接调用父类的构造器。在Scala的构造器中,你不能调用super ( params)
动态绑定机制
当调用对象方法的时候,该方法会和该对象的内存地址绑定
当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
匿名子类
通过包含带有定义或重写的代码块的方式创建一个匿名的子类
class Person {
}
class User extends Person {
}
(2)单例对象(伴生对象)
JAVA单例模式: 一个类对外只提供一个对象, 不能让外界直接实例化该类对象.
步骤: 1. 构造器私有化
2. 类的内部对外提供一个该类的对象 公共的静态常量或者方法
伴生类需要通过构建对象来访问其中的属性和方法
而伴生对象可以直接访问其属性和方法,所以一般将静态方法放置在伴生对象中,将成员方法放置在伴生类中
伴生对象是可以直接访问伴生类中的私有内容
如果使用伴生对象来构建伴生类对象的场合,可以自动识别 一个方法 : apply
指定类的对象只能创建一个,而不能创建多个,
这样的对象可以由特殊的设计方式获得,也可以由语言本身设计得到,比如object 伴生对象
Scala编译器可以通过伴生对象的apply方法创建伴生类对象。apply方法可以重载,并传递参数,且可由Scala编译器自动识别。所以在使用时,其实是可以省略的。
class User {
}
object User {
def apply( ) = new User( )
}
. . .
val user1 = new User( )
Val user2 = User. apply( )
val user3 = User( )
(3)特质的用法及功能
1 ) 基本语法
Scala中没有接口的概念. java 中所有的接口在scala中都当成特质来用
接口只和当前实现类有关系,和父类,子类没有任何关系
而是采用特殊的关键字* * trait * * 来声明特质
trait 在编译时其实就是接口,但是一般会将特质理解为接口和抽象类的结合体
如果一个类符合某一个特征(特质),那么就可以将这个特征(特质)“混入”到类中。这种混入的操作可以在声明类时使用,也可以在创建类对象时动态使用。
trait Operator {
}
trait DB{
}
class MySQL extends Operator with DB{
}
2 ) 动态混入
如果一个类混入一个特质,那么使用extends 关键字进行混入操作
如果一个类有父类,但是又混入特质,采用with 关键字进行混入
如果有多个特质需要混入,也采用with
object ScalaTrait{
def main( args: Array[ String ] ) : Unit = {
val mysql = new MySQL with Operator
mysql. insert( )
}
}
trait Operator {
def insert( ) : Unit = {
println( "insert data..." )
}
}
class MySQL {
}
3 ) 初始化叠加
object Scala10_Interface_1 {
def main( args: Array[ String ] ) : Unit = {
new F( )
}
trait A {
println( "aaaa" )
}
trait B {
println( "bbbb" )
}
trait E {
println( "eeee" )
}
class C extends B {
println( "cccc" )
}
class D extends C with E {
println( "dddd" )
}
class F extends B with A with E {
println( "ffff" )
}
}
new F( ) new D( )
4 ) 功能叠加
object Scala10_Interface_2 {
def main( args: Array[ String ] ) : Unit = {
new MySQL( ) . oper( )
}
trait Operate {
def oper( ) : Unit = {
println( "操作数据" )
}
}
trait DB extends Operate {
override def oper( ) : Unit = {
print( "向数据库中" )
super [ Operate] . oper( )
}
}
trait Log extends Operate {
override def oper( ) : Unit = {
print( "向日志文件中" )
super . oper( )
}
}
class MySQL extends Log with DB {
}
}
6. 集合
bject Scala01_Collection {
}
( 1 ) 不可变数组
object Scala02_Array {
def main( args: Array[ String ] ) : Unit = {
val array = new Array[ String ] ( 3 )
println( array. length)
array( 0 ) = "zhangsan"
array( 1 ) = "lisi"
array( 2 ) = "wangwu"
array. update( 0 , "zhaoliu" )
for ( i <- array ) {
println( i)
}
println( array. mkString( "," ) )
def foreachFuntion( s: String ) : Unit = {
println( s)
}
array. foreach( println( _) )
array. foreach( println)
}
}
( 2 ) 可变数组
object Scala02_Array_2 {
def main( args: Array[ String ] ) : Unit = {
val buffer1 = ArrayBuffer( 1 , 2 , 3 , 4 )
val buffer2 = ArrayBuffer( 1 , 2 , 3 , 4 )
buffer1. append( 5 , 6 , 7 , 8 )
buffer1. appendAll( buffer2)
buffer1. insert( 2 , 9 , 0 )
buffer1. update( 0 , 8 )
buffer1( 0 ) = 8
buffer1. remove( 2 )
buffer1. remove( 1 , 2 )
println( buffer1)
}
}
( 3 ) 可变和不可变数组之间的转换
import scala. collection. mutable
import scala. collection. mutable. ArrayBuffer
object Scala02_Array_3 {
def main( args: Array[ String ] ) : Unit = {
val array = Array( 1 , 2 , 3 , 4 )
val buffer = ArrayBuffer( 5 , 6 , 7 , 8 )
val buffer1: mutable. Buffer[ Int ] = array. toBuffer
val array1: Array[ Int ] = buffer. toArray
}
}
7. 模式匹配
8. 异常
9. 隐式转换
10. 泛型