hangscer

类型擦除以及scala如何绕过擦除

2017/05/07

思考以下java代码:

1
2
3
4
5
6
7
8
class Elvis{
public void fun(List<String> stringList){
stringList.stream().forEach(System.out::println);
}
public void fun(List<Integer> integerList){
integerList.stream().forEach(System.out::println);
}
}

以上代码是不可以运行的,由于编译器的类型擦除,报错提示为both methods have same erasure.

如何使用scala绕过类型擦除呢?

技术上讲,类型擦除是无法避免的.

1
2
3
4
object M{
def fun(seq:Seq[String])={println(s"seq[String]:$seq")}
def fun(seq:Seq[Int])={println(s"seq[Int]:$seq")}
}

这段代码与以上的java代码片段犯了同样的错误,类型擦除后,两个函数的签名相同.为了绕开类型擦除,需要使用隐式参数:

1
2
3
4
5
6
7
8
9
object M{
import predef.{IntMarker,StringMarker}
def fun(seq:Seq[String])(implicit s:StringMarker.type )={println(s"seq[String]:$seq")}
def fun(seq:Seq[Int])(implicit i:IntMarker.type)={println(s"seq[Int]:$seq")}
}
object predef{
implicit object IntMarker
implicit object StringMarker
}

上述代码中定义了两个特殊用途的隐式对象,并没有改变类型擦除,而是改变了方法的签名,从而消除二义性.