import scala.reflect.runtime.universe._ import scala.reflect.{ClassTag, classTag} object Test extends App { Test1 Test2 } class Foo[T](x: T) trait Bar[T] { def f: T } object Test1 extends TestUtil { print(()) print(true) print('a') print(1) print("abc") print('abc) println() print(List(())) print(List(true)) print(List(1)) print(List("abc")) print(List('abc)) println() //print(Array(())) //Illegal class name "[V" in class file Test$ print(Array(true)) print(Array('a')) print(Array(1)) print(Array("abc")) print(Array('abc)) println() print(((), ())) print((true, false)) print((1, 2)) print(("abc", "xyz")) print(('abc, 'xyz)) println() print(Test) print(List) println() print(new Foo(2)) print(new Foo(List(2))) print(new Foo(new Foo(2))) print(new Foo(List(new Foo(2)))) println() print(new Bar[String] { def f = "abc" }); {print(new Bar[String] { def f = "abc" })} println() } object Test2 { import Marshal._ println("()="+load[Unit](dump(()))) println("true="+load[Boolean](dump(true))) println("a="+load[Char](dump('a'))) println("1="+load[Int](dump(1))) println("'abc="+load[scala.Symbol](dump('abc))) println() println("List(())="+load[List[Unit]](dump(List(())))) println("List(true)="+load[List[Boolean]](dump(List(true)))) println("List('abc)="+load[List[scala.Symbol]](dump(List('abc)))) println() def loadArray[T](x: Array[Byte])(implicit t: reflect.ClassTag[Array[T]]) = load[Array[T]](x)(t).deep.toString println("Array()="+loadArray[Int](dump(Array(): Array[Int]))) println("Array(true)="+loadArray[Boolean](dump(Array(true)))) println("Array(a)="+loadArray[Char](dump(Array('a')))) println("Array(1)="+loadArray[Int](dump(Array(1)))) println() println("((),())="+load[(Unit, Unit)](dump(((), ())))) println("(true,false)="+load[(Boolean, Boolean)](dump((true, false)))) println() println("List(List(1), List(2))="+load[List[List[Int]]](dump(List(List(1), List(2))))) println() println("Array(Array(1), Array(2))="+loadArray[Array[Int]](dump(Array(Array(1), Array(2))))) println() } object Marshal { import java.io._ import scala.reflect.ClassTag def dump[A](o: A)(implicit t: ClassTag[A]): Array[Byte] = { val ba = new ByteArrayOutputStream(512) val out = new ObjectOutputStream(ba) out.writeObject(t) out.writeObject(o) out.close() ba.toByteArray() } @throws(classOf[IOException]) @throws(classOf[ClassCastException]) @throws(classOf[ClassNotFoundException]) def load[A](buffer: Array[Byte])(implicit expected: ClassTag[A]): A = { val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) val found = in.readObject.asInstanceOf[ClassTag[_]] try { found.runtimeClass.asSubclass(expected.runtimeClass) in.readObject.asInstanceOf[A] } catch { case _: ClassCastException => in.close() throw new ClassCastException("type mismatch;"+ "\n found : "+found+ "\n required: "+expected) } } } trait TestUtil { import java.io._ def write[A](o: A): Array[Byte] = { val ba = new ByteArrayOutputStream(512) val out = new ObjectOutputStream(ba) out.writeObject(o) out.close() ba.toByteArray() } def read[A](buffer: Array[Byte]): A = { val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) in.readObject().asInstanceOf[A] } def print[T](x: T)(implicit t: TypeTag[T]) { // todo. type tags are not yet serializable // val t1: TypeTag[T] = read(write(t)) val t1: TypeTag[T] = t val x1 = x.toString.replaceAll("@[0-9a-z]+$", "") println("x="+x1+", t="+t1+", k="+t1.tpe.asInstanceOf[Product].productPrefix+", s="+t1.tpe.typeSymbol.toString) } }