1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package scala
package reflect
import java.lang.{ Class => jClass }
import scala.language.{implicitConversions, existentials}
import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances.
*
* If an implicit value of type ClassTag[T] is requested, the compiler will create one.
* The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed
* via the `runtimeClass` field. References to type parameters or abstract type members are
* replaced by the concrete types if ClassTags are available for them.
*
* Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi-
* dimensional `Arrays` where the element type is unknown at compile time.
*
* [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]].
*
* @see [[scala.reflect.api.TypeTags]]
*/
@scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable {
// please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
// class tags, and all tags in general, should be as minimalistic as possible
/** A class representing the type `U` to which `T` would be erased.
* Note that there is no subtyping relationship between `T` and `U`.
*/
def runtimeClass: jClass[_]
/** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass))
/** Produces a new array with element type `T` and length `len` */
override def newArray(len: Int): Array[T] =
runtimeClass match {
case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
case java.lang.Short.TYPE => new Array[Short](len).asInstanceOf[Array[T]]
case java.lang.Character.TYPE => new Array[Char](len).asInstanceOf[Array[T]]
case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
case java.lang.Long.TYPE => new Array[Long](len).asInstanceOf[Array[T]]
case java.lang.Float.TYPE => new Array[Float](len).asInstanceOf[Array[T]]
case java.lang.Double.TYPE => new Array[Double](len).asInstanceOf[Array[T]]
case java.lang.Boolean.TYPE => new Array[Boolean](len).asInstanceOf[Array[T]]
case java.lang.Void.TYPE => new Array[Unit](len).asInstanceOf[Array[T]]
case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
/** A ClassTag[T] can serve as an extractor that matches only objects of type T.
*
* The compiler tries to turn unchecked type tests in pattern matches into checked ones
* by wrapping a `(_: T)` type pattern as `ct(_: T)`, where `ct` is the `ClassTag[T]` instance.
* Type tests necessary before calling other extractors are treated similarly.
* `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
* is uncheckable, but we have an instance of `ClassTag[T]`.
*/
def unapply(x: Any): Option[T] = unapply_impl(x)
def unapply(x: Byte): Option[T] = unapply_impl(x)
def unapply(x: Short): Option[T] = unapply_impl(x)
def unapply(x: Char): Option[T] = unapply_impl(x)
def unapply(x: Int): Option[T] = unapply_impl(x)
def unapply(x: Long): Option[T] = unapply_impl(x)
def unapply(x: Float): Option[T] = unapply_impl(x)
def unapply(x: Double): Option[T] = unapply_impl(x)
def unapply(x: Boolean): Option[T] = unapply_impl(x)
def unapply(x: Unit): Option[T] = unapply_impl(x)
private def unapply_impl[U: ClassTag](x: U): Option[T] =
if (x == null) None
else {
val staticClass = classTag[U].runtimeClass
val dynamicClass = x.getClass
val effectiveClass = if (staticClass.isPrimitive) staticClass else dynamicClass
val conforms = runtimeClass.isAssignableFrom(effectiveClass)
if (conforms) Some(x.asInstanceOf[T]) else None
}
// case class accessories
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass
override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass)
override def toString = {
def prettyprint(clazz: jClass[_]): String =
if (clazz.isArray) s"Array[${prettyprint(arrayElementClass(clazz))}]" else
clazz.getName
prettyprint(runtimeClass)
}
}
/**
* Class tags corresponding to primitive types and constructor/extractor for ClassTags.
*/
object ClassTag {
private val ObjectTYPE = classOf[java.lang.Object]
private val NothingTYPE = classOf[scala.runtime.Nothing$]
private val NullTYPE = classOf[scala.runtime.Null$]
val Byte : ClassTag[scala.Byte] = Manifest.Byte
val Short : ClassTag[scala.Short] = Manifest.Short
val Char : ClassTag[scala.Char] = Manifest.Char
val Int : ClassTag[scala.Int] = Manifest.Int
val Long : ClassTag[scala.Long] = Manifest.Long
val Float : ClassTag[scala.Float] = Manifest.Float
val Double : ClassTag[scala.Double] = Manifest.Double
val Boolean : ClassTag[scala.Boolean] = Manifest.Boolean
val Unit : ClassTag[scala.Unit] = Manifest.Unit
val Any : ClassTag[scala.Any] = Manifest.Any
val Object : ClassTag[java.lang.Object] = Manifest.Object
val AnyVal : ClassTag[scala.AnyVal] = Manifest.AnyVal
val AnyRef : ClassTag[scala.AnyRef] = Manifest.AnyRef
val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
val Null : ClassTag[scala.Null] = Manifest.Null
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] =
runtimeClass1 match {
case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]]
case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 }
}
def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass)
}
|