Scala中如何对List[ScheduleChangeEvent]对象执行模式匹配
问题根源
这是JVM的泛型类型擦除机制导致的问题。
JVM运行时不会保留泛型参数的类型信息,你代码里写的List[LocationSettingsChange]、List[LocationWorkHoursChange]等带具体泛型的类型,运行时都会被统一擦除为List[_]。这就导致你写的四个case分支本质上都是匹配List类型,第一个分支会命中所有传入的非空列表,后续分支自然全部不可达,也就出现了你遇到的永远走第一个分支、报不可达代码警告的问题。
解决方案
方案1:匹配列表首元素类型(适用同列表仅含一种子类、且列表非空的业务场景)
如果你的业务逻辑可以保证queue中所有元素都是同一种ScheduleChangeEvent子类,且列表不会为空,可以用如下写法:
queue match { case (_: LocationSettingsChange) :: _ => // LocationSettingsChange 对应业务逻辑 case (_: LocationWorkHoursChange) :: _ => // LocationWorkHoursChange 对应业务逻辑 case (_: TeamParameterChange) :: _ => // TeamParameterChange 对应业务逻辑 case (_: MemberPrimaryTeamChange) :: _ => // MemberPrimaryTeamChange 对应业务逻辑 case Nil => // 空列表处理逻辑 }
方案2:先校验全列表元素类型再匹配(兼容单列表含多种子类的场景)
如果同一个列表可能包含多种子类,需要先做全量类型校验:
queue match { case l if l.forall(_.isInstanceOf[LocationSettingsChange]) => val castedList = l.asInstanceOf[List[LocationSettingsChange]] // 对应业务逻辑 case l if l.forall(_.isInstanceOf[LocationWorkHoursChange]) => val castedList = l.asInstanceOf[List[LocationWorkHoursChange]] // 对应业务逻辑 case l if l.forall(_.isInstanceOf[TeamParameterChange]) => val castedList = l.asInstanceOf[List[TeamParameterChange]] // 对应业务逻辑 case l if l.forall(_.isInstanceOf[MemberPrimaryTeamChange]) => val castedList = l.asInstanceOf[List[MemberPrimaryTeamChange]] // 对应业务逻辑 case Nil => // 空列表处理逻辑 }
方案3:使用TypeTag做运行时泛型校验(不推荐)
如果必须直接匹配带泛型的List类型,可以引入scala.reflect.runtime.universe.TypeTag实现运行时泛型参数校验,不过该方案性能较差、依赖反射,普通业务场景不建议使用。
内容的提问来源于stack exchange,提问作者TreyBCollier
相关产品推荐
相关产品推荐

