我正在閱讀有關型別擦除的資訊,here
case class Thing[T](value: T)
def processThing(thing: Thing[_]) = {
thing match {
case Thing(value: Int) => "Thing of int" //isn't thing Thing[_] anymore?
case Thing(value: String) => "Thing of string" //isn't thing Thing[_] anymore?
case Thing(value: Seq[Int]) => "Thing of Seq[Int]" //value=Seq[_] really
case Thing(value: Seq[String]) => "Thing of Seq[String]" //value=Seq[_] really
case _ => "Thing of something else"
}
}
println(processThing(Thing(Seq(1,2,3)))) //type erased, I get it
println(processThing(Thing(Seq("hello", "yo")))) //type erased, I get it
println(processThing(Thing(1))) //why is this working?
println(processThing(Thing("hello"))) //why is this working?
我理解為什么 Seq[Int] 和 Seq[String] 沒有被正確識別,在運行時兩者都被視為 Seq[Object]。
但是,我不明白為什么前兩個示例有效:為什么 Thing[Int] 和 Thing[String],兩者都是 Thing[T] 沒有 Seq[T] 的相同問題......
為什么 Thing[Seq[T]] 型別被擦除但 Thing[T] (T=Int, String) 不是?
誰能解釋這里發生了什么?謝謝
uj5u.com熱心網友回復:
你是對的,在運行時兩者Thing(1)都會Thing("Hello")擦除到同一個類Thing。
因此,如果您執行以下操作:
thing match {
case _: Thing[Int] => foo
case _: Thing[String] => bar
}
您會看到預期的行為。
但是,您的模式匹配正在做一些不同的事情,它提取里面的值thing,然后對其進行類檢查。該值的類資訊是自己保留的,因此您可以區分Int,String和Seq,但是您看不到Seq
But 的型別引數是什么,您可以嘗試檢查Seq... 但是的第一個元素這仍然不夠,因為第一個元素可能是 aDog而第二個元素是 aCat因為它是 aSeq[Animal]并且該檢查比以前的檢查更加不安全,因為Seq可能是空的。
uj5u.com熱心網友回復:
考慮以下 Java 代碼:
class Foo {
<T> void bar(T whatIsIt) {
System.out.println("It is a: " whatIsIt.getClass().getName());
}
public static void main() {
Foo f = new Foo();
f.bar(123);
f.bar("Hello world");
f.bar(f);
f.bar(new ArrayList<String>());
}
}
在運行時只存在一種方法Foo#bar(Object)。但是傳入的物件whatIsIt仍然有一個指向它實際上是什么類的指標。
Scala 可以訪問與 Java 相同的元資料。因此,當它為其構建位元組碼時,processThing它可以插入value instanceOf Integer- 這就是它的作用:
scala> :javap processThing
// ... snip ...
public java.lang.String processThing($line3.$read$$iw$Thing<?>);
descriptor: (L$line3/$read$$iw$Thing;)Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=8, args_size=2
0: aload_1
1: astore_3
2: aload_3
3: ifnull 29
6: aload_3
7: invokevirtual #37 // Method $line3/$read$$iw$Thing.value:()Ljava/lang/Object;
10: astore 4
12: aload 4
14: instanceof #39 // class java/lang/Integer
17: ifeq 26
20: ldc #41 // String Thing of int
// ... snip ...
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/422301.html
標籤:
上一篇:Scala決議泛型型別很痛苦
