泛型
就是一种不确定的数据类型,可以支持多种类型
定义泛型方法
在scala中,使用方括号来定义类型参数。
语法格式
def 方法名[泛型名称](..) = {
//...
}
代码示例
object Test01 {
/**
* 没有泛型支持
*
* @param array 接收一个int 型的集合
* @return 返回集合长度除以2 所对应索引的值
*/
def getMiddle(array: Array[Int]): Int = array(array.length / 2)
/**
* 有泛型支持
* @param array 接收一个集合
* @tparam T 集合可以是任意类型
* @return 返回集合长度除以2 所对应索引的值
*/
def getMiddleElement[T](array: Array[T]): T = {
array(array.length / 2)
}
def main(args: Array[String]): Unit = {
//调用 getMiddle 方法
println(Array(1,2,3,4,5))
//调用getMiddleElement 方法
println(getMiddleElement(Array(1,2,3,4,5)))
println(getMiddleElement(Array("a","b","c","d","e")))
}
}
定义泛型类
语法格式
- 定义一个泛型类,直接在类名后面加上方括号,指定要使用的泛型参数
- 指定类对应的泛型参数后,就使用这些类型参数来定义变量了
class 类[T](val 变量名: T)
代码示例
object Test02 {
//定义一个 Pair泛型类
//Pair类包含两个字段,而且两个字段的类型不固定
case class Pair[T](var a: T, var b: T)
def main(args: Array[String]): Unit = {
//创建不同类型泛型类对象
val pair1 = Pair("hadoop","Storm")
val pair2 = Pair("hadoop",2018)
val pair3 = Pair(1.2,3.0)
val pair4 = Pair("hadoop",Some(1.9))
//打印
println(s"p = ${pair1}")
println(s"p = ${pair2}")
println(s"p = ${pair3}")
println(s"p = ${pair4}")
}
}
泛型上下界
我们在定义方法/类的泛型时,限定必须从哪个类继承、或者必须是哪个类的父类。此时,就需要使用到上下界。
上界定义
使用
<: 类型名
表示给类型添加一个上界,表示泛型参数必须要从该类(或本身)继承
语法格式
[T <: 类型]
上界代码示例
object Test03 {
//定义一个Person类
class Person
//定义一个Student类,继承Person类
class Student extends Person
def demo[T <:Person](a:Array[T]): Unit = println(a)
def main(args: Array[String]): Unit = {
//编译成功 因为是 Person 的子类
demo(Array(new Person))
demo(Array(new Student))
//编译出错, 必须是Person的子类
// demo(Array("hadoop"))
}
}
下界定义
上界是要求必须是某个类的子类,或者必须从某个类继承,而下界是必须是某个类的父类(或本身)
如果类既有上界、又有下界。下界写在前面,上界写在后面
语法格式
[T >: 类型]
下界代码示例
object Test04 {
//定义一个Person类
class Person
//定义一个Policeman类,继承Person类
class Policeman extends Person
//定义一个Superman类,继承Policeman类
class Superman extends Policeman
/**
* 定义一个demo泛型方法
* 限定demo方法的Array元素类型只能是Person、Policeman
* @param array 接收一个Array参数
* @tparam T 泛型
*/
def demo[T >: Policeman](array: Array[T]): Unit = println(array)
def main(args: Array[String]): Unit = {
//编译成功
demo(Array(new Person))
demo(Array(new Policeman))
//运行时报编译 报错 Superman是Policeman的子类 不是父类
// demo(Array(new Superman))
}
}
泛型 协变、逆变、非变
非变
- 默认泛型类是非变的,类型B是A的子类型,
- Pair[A]和Pair[B]没有任何从属关系
协变
- 协变参数化类型的方向和类型的方向是一致的。
- 类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型
逆变
- 逆变参数化类型的方向和类型的方向是相反的
- 类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型
语法格式
//非变
class Pair[T]
//协变
class Pair[+T]
//逆变
class Pair[-T]
代码示例
object Test05 {
//定义一个Super类、以及一个Sub类继承自Super类
class Super
class Sub extends Super
//非变
class Temp1[T]
//协变
class Temp2[+T]
//逆变
class Temp3[-T]
def main(args: Array[String]): Unit = {
val a: Temp1[Sub] = new Temp1[Sub]
//编译报错
//非变
// val b:Temp1[Super] =a
//协变
val c: Temp2[Sub] = new Temp2[Sub]
val d: Temp2[Super] = c
//逆变
val e: Temp3[Super] = new Temp3[Super]
val f: Temp3[Sub] = e
}
}