泛型在Scala和Java中类似,用于类或者方法用于指定任意类型 或者一种类型的参数,参数在使用的时候才会被确定,泛型可以有效的增强程序的灵活性,使用泛型的目的是可以使得类或者方法具有更高的通用性,或者作为一种规范。
泛型可以用于类,也可以用于方法,比如:
类中的泛型:
class CommonData[T]{
private var data: T = _
def get():T = data
def set(value:T) = data = value
}
这个简单的泛型,可以指定任意类型,比如说Int,String等
方法中的泛型,比如定一个数组:
// ClassTag 表示的是运行状态的信息,这里表示的是运行的时候的类型
def makeArray[T:ClassTag](element: T*) = Array[T](element:_*)
def main(args: Array[String]): Unit = {
val demo = new ListDemo().makeArray[String]("1", "3")
demo.foreach(s=>println(s))
}
调用的时候指定类型即可。 其中的T* 表示的可变参数
泛型的规则:
- 泛型的上边界和下边界
上边界: 表示泛型的类型必须是 某种类型的子类,表示为 <:
下边界: 表示泛型的类型必须是 某种类型的父类,表示为 >:
比如:
class Test1[T <: Comparable[T]]{
}
- 协变和逆变
协变: 在类型参数的前面加上一个 +
逆变: 在类型参数前面加上一个 -
这里可以类比一下,我们在Java中我们可以
Object str = new String();一个子类可以赋值给一个父类,这样的编译器是允许的。
但是你不可以这样:ArrayList list = new ArrayList();
这样在Java中编译不会通过的,但是在Scale中就可以
比如:
val list:List[AnyRef] = ListString 原因就是协变。
再比如:
class Person1{}
class Student1 extends Person1{
def sayOut: Unit ={
println("Student")
}
}
class CommonData[+T](t:T){}
val data = new CommonData[Student1](new Student1())
val data1:CommonData[Person1] = data
这意味着支持泛型T的子类可以向支持T的类赋值,这个是协变。
逆变正好相反,如下:
class Person1{}
class Student1 extends Person1{}
class CommonData[-T](t:T){}
val data = new CommonData[Person1](new Person1())
val data1:CommonData[Student1] = data
欢迎关注我的公众号: manong_xiaodong。