java 泛型數組初始化
public class GenericArray<T> {
private T[] arr;
public GenericArray(){
arr = new T[10]; //編譯錯誤
}
}
使用這樣的方式初始化java的數組會出錯,因為java不支持泛型數組。按照我的理解,java 初始化數組時候,需要知道數組的確切類型,但是泛型是編譯后擦除的。所以運行時,無法知道數組的確切類型。所以java不支持以 new T[] 方式初始化一個數組。
如果想進行初始化,可以通過這樣的方式
T[] arr=(T[]) new Object[10];
scala的泛型數組
那么同樣的場景,在scala中如何實現呢
class ScalaGenericArray[T]{
val arr: Array[T] = new Array[T](10)
}
object ScalaGenericArray{
def main(args: Array[String]): Unit = {
val arr = new ScalaGenericArray[String]
}
}
看起來很自然,但是在運行時候會報錯:
Error:(9, 23) cannot find class tag for element type T
val arr: Array[T] = new Array[T](10)
原因和java的一樣,虛擬機中,泛型相關的類型信息會被擦除,所以無法將T解釋成實際類型String
那么如何做呢,此處我們需要將類型的信息以一個參數的方式傳進去
class ScalaGenericArray[T](implicit classTag:ClassTag[T] ){ //讓編譯器幫我們傳入類型信息
val arr: Array[T] = new Array[T](10)
}
object ScalaGenericArray{
def main(args: Array[String]): Unit = {
val arr = new ScalaGenericArray[String]
}
}
- 感覺這種方式有點類似于java為了獲取一個泛型的信息,將類以參數的形式傳入函數參數中
public <T> T test(Class<T> clazz) {
System.out.println(clazz);
//...
}
當然此處的ClassTag也可以使用Manifest,但是在scala 2.10.0后就不推薦使用了
這樣寫比較復雜,scala也提供另一種簡單的方式,上下文界定
class ScalaGenericArray[T: ClassTag] {//此處不再需要提供參數
val arr: Array[T] = new Array[T](10)
}
object ScalaGenericArray {
def main(args: Array[String]): Unit = {
val arr = new ScalaGenericArray[String]
}
}
這是scala的語法糖,T:ClassTag 告訴scala存在一個類型為ClassTag[T] 的隱式參數