一:简介
泛型就是指模糊的数据类型,不是具体的数据类型,在类的声明时可以定义泛型,定义后就可以在类的属性或者方法中使用这些泛型了。在创建对象时需要指定泛型定义时对应的具体数据类型。泛型就是把数据类型作为参数传递到类中去。
如果想让属性的数据类型或者方法的参数或者返回值可以接收任意类型的值,我们可以将类型定义为Any,但是在拿到返回值时我们还需要强制类型转换,使用泛型就不用强制类型转换,定义什么类型就返回什么类型。
二:语法
- 泛型可以定义在类上被称为泛型类,也可以定义在方法上被称为泛型方法。
- 泛型类型可以用任意字符表示,习惯上使用T、A、B表示
- 泛型使用中括号[]来定义,直接跟在类名后面,中括号中间可以有多个类型,如
[T, T1, T2]
, 属性的类型是泛型可以将下划线_作为初始值来为属性赋值 - 泛型作为方法的返回值时需要使用asInstanceOf[B]将返回值的类型转换一下
- 泛型上边界使用符号 <: 来定义,即 [ T <: Xxx], 即 T 是能是Xxx或者Xxx的子类。
- 泛型下边界使用符号 >: 来定义, 即 [ T >: Xxx], 即 T 是能是Xxx或者Xxx的父类。
- 泛型协变[+T] : 用于定义在类上,作为方法的参数可以是T类或者T类的子类
- 泛型逆变[-T]: 用于定义在类上,作为方法的参数可以是T类或者T类的父类
/**
* 泛型基本使用示例
*/
// 人
class Person[T, T2, T3](var name: T) {
var age: T2 = _
var address: T3 = _
// 泛型函数
def say[T4, T5, B1](param1: T4, param2: T5): B1 = {
val result = param1.equals(param2)
result.asInstanceOf[B1]
}
}
// 中国人
class Chinese extends Person
// 上海人
class ShanghaiPeople extends Chinese
// 上海浦东人
class ShPuDongPeople extends ShanghaiPeople
// 上海 浦东 张江人
class PuDongZhangJiangPeople[ T <: Chinese, T2 >: ShanghaiPeople] extends Chinese {
def sayHello(t: T, t2: T2): Unit = {
println("浦东张江侬好:" + t.getClass + "\t" + t2.getClass)
}
}
object Main {
def main(args: Array[String]): Unit = {
val person = new Person[String, Int, String]("mengday")
person.age = 28
person.address = "SH"
val result = person.say[String, Int, Boolean]("mengday", 28)
println(result)
val zhangjiangPeople = new PuDongZhangJiangPeople[ShanghaiPeople, Chinese]()
val shanghaiPeople = new ShanghaiPeople
val chinese = new Chinese
zhangjiangPeople.sayHello(shanghaiPeople, chinese)
}
}
/**
* 协变和逆变
*/
class Person
class Chinese extends Person
class ShPeople extends Chinese
// 协变:T或T的子类
class Foobar[+T]
// 逆变: T或T的父类
class Foobaz[-T]
class Test {
// 协变:虽然将参数类型定义为Foobar[Person],但因Foobar不是普通类型是协变的,所以Foobar[Person]不仅仅是具体的Foobar[Person]也能匹配上Foobar[Person的子类]
def say(foobar: Foobar[Person]): Unit = {
println("say=" + foobar.getClass)
}
// 逆变:这里虽然定义了Foobaz[Chinese]因Foobaz是逆变类型,所以Foobaz[Chinese]既能匹配到Foobaz[Chinese]也能匹配到Foobaz[Chinese的父类]
def sayHello(foobaz: Foobaz[Chinese]): Unit = {
println("sayHello:" + foobaz.getClass)
}
}
object Main {
def main(args: Array[String]): Unit = {
val foobarPerson = new Foobar[Person]
val foobarChinese = new Foobar[Chinese]
//Foobar[+T]: Foobar[Person] 和 Foobar[Chinese] 都是 Foobar[Person]类型
val test = new Test
test.say(foobarPerson)
test.say(foobarChinese)
//Foobaz[-T]: Foobaz[Chinese] 和 Foobaz[Person] 都能匹配Foobaz[Chinese]类型
val chinese = new Foobaz[Chinese]
val person = new Foobaz[Person]
test.sayHello(chinese)
test.sayHello(person)
}
}