文章目录
泛型
- 安全:将运行时期可能出现类型错误转换到了编译期
- 避免类型转换
List list = new ArrayList();
list.add("aa")
list.add(10)
Object obj = list.get(0);
Java泛型回顾
- 泛型类
- 泛型方法
- 上边界
- 下边界
- 无固定边界
// 1. 泛型类
// 2. 泛型方法
// 3. 上边界
// 4. 下边界
// 5. 无固定边界
package generic.java;
import scala.actors.threadpool.Arrays;
import java.util.ArrayList;
import java.util.List;
/**
* java 泛型学习
*/
public class GenericTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("aa");
list.add(10);
String aa = (String) list.get(0);
System.out.println(aa);
List<String> list2 = new ArrayList<String>();
list2.add("aa");
String aa2 = list2.get(0);
System.out.println(aa2);
A<String, Integer, Double> a1 = new A<String, Integer, Double>();
a1.setT("zs");
String name = a1.getT();
System.out.println(name);
a1.m1(10.0);
a1.m1(10L);
a1.m1(3.14F);
ArrayList<C> list3 = new ArrayList<C>();
ArrayList<B> list4 = new ArrayList<B>();
ArrayList<String> list5 = new ArrayList<String>();
a1.m2(list3);
a1.m2(list4);
// a1.m2(list5); //error
ArrayList<C> list6 = new ArrayList<C>();
ArrayList<B> list7 = new ArrayList<B>();
ArrayList<String> list8 = new ArrayList<String>();
a1.m3(list6);
a1.m3(list7);
ArrayList<C> list9 = new ArrayList<C>();
ArrayList<B> list10 = new ArrayList<B>();
ArrayList<String> list11 = new ArrayList<String>();
a1.m4(list9);
a1.m4(list10);
a1.m4(list11);
}
}
// 泛型类
class A<T, S, K> {
private T t;
private S s;
private K k;
// 泛型方法 M类型必须是Number类型的子类型
public <M extends Number> void m1(M m) {
System.out.println(m);
}
// 上边界 必须为B类型的子类
public void m2(List<? extends B> list) {
list.forEach(n -> System.out.println(n));
}
// 下边界 ? 类型必须是C类型的父类型
public void m3(List<? super C> list){
list.forEach(n-> System.out.println(n));
}
// 无固定边界 泛型无固定
public void m4(List<?> list){
list.forEach(n-> System.out.println(n));
}
public T getT() {
return this.t;
}
public void setT(T t) {
this.t = t;
}
}
class B {
}
class C extends B {
}
Scala 泛型类
语法: 类名[泛型类型,....]
package generic
/**
* 泛型类
*/
object GenericClass {
def main(args: Array[String]): Unit = {
var a: A[String] = new A[String]
val t = a.t //null
println(t)
val b = new B[String,Double,Int]("ABC",90,90)
println(b) // ABC 90.0 90
}
}
class A[T]{
var t: T = _
}
// 泛型类
class B[T,M,N](t:T,m:M,n: N){
override def toString: String = t + "\t" + m + "\t" + n
}
Scala 泛型方法
约束方法中的形参类型
package generic.scala
import scala.collection.mutable
object GenericMethod {
def main(args: Array[String]): Unit = {
print[String](Array("abc", "efg", "xyz"))
print(Array("abc", "efg", "xyz"))
print(Array[Any]("abc", "efg", "xyz", 10)) //OK
// print(Array[String]("abc", "efg", "xyz",10)) //ERROR
ret[String](Array("abc", "efg", "xyz"))
}
/**
* 泛型方法
*
* @param arr
* @tparam K
*/
def print[K](arr: Array[K]): Unit = {
arr.foreach(println)
}
def ret[M](arr: Array[M]): mutable.Buffer[M] = {
arr.toBuffer
}
}
上边界&下边界
上边界: 语法:[T <: S]
,T类型必须是S类型的子类型,包含S类型本身
下边界: 语法:[T >: S]
,T类型必须是S类型的父类型,包含S类型本身
package generic
/**
* 上边界 和 下边界
*
*/
object GenericUpperAndLowerBound {
def main(args: Array[String]): Unit = {
val b1 = new Cc[Bb]
val b2 = new Cc[Aa]
// val b3 = new Cc[Dd] // error
val a1 = new Ee[Aa]
val a2 = new Ee[Ff]
// val a3 = new Ee[Bb] // error
}
}
class Aa extends Ff
class Bb extends Aa
// 上边界,K为Aa的子类
class Cc[K <: Aa]{
}
class Dd
// 下边界,k为Aa的父类
class Ee[K >: Aa]
class Ff
视图边界
语法:[T <% S]
, 运行时尝试将T类型隐式转换为S类型,要求当前类或者作用域存在隐式转换;
package generic.view
import java.text.SimpleDateFormat
import scala.collection.mutable
/**
* 视图边界
* 将泛型转为定义的类型,需要存在一个隐式转换
*/
object ViewBound {
def main(args: Array[String]): Unit = {
val a = new A[String]("2020-01-01 13:00:01")
a.printDate()
}
// string 转为 Date 的隐式转换器
implicit def stringToDate(date: String): java.util.Date ={
val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
format.parse(date)
}
}
// 泛型转为 Date 类型
class A[K <% java.util.Date](k: K){
def printDate(): Unit ={
val date = new java.util.Date(k.getTime) // 使用时间戳 创建出一个日期对象
val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") // 格式化日期对象
println(format.format(date))
}
}
class Animal{
def eat(): Unit ={
println("Animal is eating")
}
}
// ----------- 视图边界 ------------
class Dog
class S[k <% Animal]
object Dd extends App{
var value = new S[Dog]
value.eat()
// 隐式转换 泛型
implicit def dogToAnimal(dog: Dog): Animal={
new Animal
}
// 隐式转换 S[Dog] 类型 转为Animal类型
implicit def sToAnimal(s:S[Dog]): Animal = {
new Animal
}
}
多重限定
多重上界
语法:[T <: S with K]
表示T类型必须同时是S类型和K类型的子类型
多重下界
语法:[T >: S with K]
表示T类型必须S类型或者K类型的父类型
多重上界需要同时为泛型的子类
下界满足一个父类
package generic.multi
/**
* 多重上界 多重下界
*/
object GeneriUpper {
def main(args: Array[String]): Unit = {
val z1 = new Z[C]
val z2 = new Z[B]
// val z3 = new Z[A] // error
val x1 = new X[Y]
val x2 = new X[A]
val x3 = new X[B]
val x4 = new X[C]
}
}
class Y
class A extends Y
class B extends A
class C extends B
// 泛型必须为B和A的子类型
class Z[T <: B with A]
// 泛型必须为 B或者C的父类
class X[T >: B with C]
既有上界又有下界
语法:[T >: S <: K]
表示T类型的上边界为K类型,下边界为S类型
package generic.multi
/**
* 既有上界 又有下界
* 语法:`[T >: S <: K]` 表示T类型的上边界为K类型,下边界为S类型
*/
object MutiUpperBound {
def main(args: Array[String]): Unit = {
val c1 = new CC[DD]
val c2 = new CC[BB]
val c3 = new CC[AA]
// val c4 = new CC[EE] // error
}
}
class AA
class BB extends AA
class DD extends BB
class EE extends DD
// T类型必须是DD类型的父类型,AA类型的子类型 包含上下界本身
class CC[T >: DD <: AA]
协变
语法:
[+T]
如果T类型是T1类型的父类型,则 C[T]类型是C[T1]类型的父类
泛型为父子关系,使用泛型后也为父子关系
package generic.xb
/**
* 协变
* 语法:`[+T]`
*
* 如果T类型是T1类型的父类型,则 C[T]类型是C[T1]类型的父类
*/
object GenericXB {
def main(args: Array[String]): Unit = {
val c1 = new C[B]
val c2: C[A] = c1
}
}
class A
class B extends A
// 泛型A 的父类是B 那么C[A]就是C[B]的父类
class C[+T]
逆变
语法:[-T]
如果T类型是T1类型的父类型,则C[T]类型是C[T1]类型的子类型
父子关系逆向
package generic.nb
/**
* 逆变
* 语法:[-T]
*
* 如果T类型是T1类型的父类型,则C[T]类型是C[T1]类型的子类型
*/
object GenericNB {
def main(args: Array[String]): Unit = {
val x1 = new X[A]
val x2: X[B] = x1
}
}
class A
class B extends A
// 泛型A 的父类是B 那么C[B]就是C[A]的父类
class X[-T]
不变
语法:
[T]
使用泛型后不改变任何属性
上下文限定(拓展)
语法:
[T:M]
上下文界定的形式为T:M,其中M是另一个泛型类,它要求必须存在一个类型为M[T]的隐式值。implicit val ordering:Ordering[Person] = new Ordering(){} [T:Ordering] implicitly[Ordering[T]]
package generic.scala.contextbound
// 语法:`[T:M]`
//
// 上下文界定的形式为T:M,其中M是另一个泛型类,它要求必须存在一个类型为M[T]的隐式值。
class Person(var name: String, var age: Int)
object Person {
// 声明ordering[Person]的隐式值【对象】
implicit val ordering: Ordering[Person] = new Ordering[Person] {
override def compare(x: Person, y: Person): Int = if (x.age > y.age) 1 else -1
}
def main(args: Array[String]): Unit = {
val p1 = new Person("zs", 20)
val p2 = new Person("ls", 30)
val tools = new CompareUtils[Person](p1, p2)
if(tools.compare == 1){
println("大于")
}else{
println("小于")
}
}
}
/**
* T: 泛型类(Ordering)
*
* T:M M必须是泛型类,并且必须提供同类型的隐式值
*
* @tparam T
*/
class CompareUtils[T: Ordering](p1: T, p2: T) {
def compare: Int = {
val ordering = implicitly[Ordering[T]] // 获取一个Ordering[T]隐式值
ordering.compare(p1,p2)
}
}