This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Get scala.reflect.Manifest[_] from java.lang.reflect.Type

7 replies
gerferra
Joined: 2009-08-26,
User offline. Last seen 1 year 38 weeks ago.
Hi,
It's possible to get the convertion mentioned in the subject? I'm looking for a way to get a Manifest for the type of a field obtained by reflection.
Regards,Germán.
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type

On Sat, Aug 07, 2010 at 07:54:23PM -0300, Germán Ferrari wrote:
> It's possible to get the convertion mentioned in the subject? I'm
> looking for a way to get a Manifest for the type of a field obtained
> by reflection.

It would not be difficult to write, but it isn't in the distribution
(yet, maybe.) It'd look something like

def javaType(tp: reflect.Type): Manifest[_] = tp match {
case x: Class[_] => Manifest.classType(x)
case x: ParameterizedType =>
Manifest.classType(x.getRawType(), x.getActualTypeArguments() map javaType : _*)

...etc. Don't take that code too literally, but I don't see why the
full implementation would be more than 8 or so lines.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type

On Sat, Aug 07, 2010 at 07:54:23PM -0300, Germán Ferrari wrote:
> It's possible to get the convertion mentioned in the subject? I'm
> looking for a way to get a Manifest for the type of a field obtained
> by reflection.

OK, I'm not so good at not doing things I say will be 8 lines. This is
not entirely complete but see how it goes. It does pass the amazing 1
test suite.

object Ref {
import java.lang.reflect.{ Type => JType, Array => _, _ }
import scala.reflect.Manifest.{ classType, intersectionType, arrayType, wildcardType }

def intersect(tps: JType*): Manifest[_] = intersectionType(tps map javaType: _*)
def javaType(tp: JType): Manifest[_] = tp match {
case x: Class[_] => classType(x)
case x: ParameterizedType =>
val owner = x.getOwnerType
val raw = x.getRawType() match { case clazz: Class[_] => clazz }
val targs = x.getActualTypeArguments() map javaType

(owner == null, targs.isEmpty) match {
case (true, true) => javaType(raw)
case (true, false) => classType(raw, targs.head, targs.tail: _*)
case (false, _) => classType(javaType(owner), raw, targs: _*)
}
case x: GenericArrayType => arrayType(javaType(x.getGenericComponentType))
case x: WildcardType => wildcardType(intersect(x.getLowerBounds: _*), intersect(x.getUpperBounds: _*))
case x: TypeVariable[_] => intersect(x.getBounds(): _*)
}
}

object Test {
import Ref._
class MappyDo extends java.util.HashMap[String, String] { }

def main(args: Array[String]): Unit = {
val m1 = javaType(classOf[MappyDo].getGenericSuperclass)
val m2 = manifest[java.util.HashMap[String, String]]

assert(m1 == m2)
}
}

gerferra
Joined: 2009-08-26,
User offline. Last seen 1 year 38 weeks ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type
Thank you!


On Sun, Aug 8, 2010 at 2:52 AM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Sat, Aug 07, 2010 at 07:54:23PM -0300, Germán Ferrari wrote:
> It's possible to get the convertion mentioned in the subject? I'm
> looking for a way to get a Manifest for the type of a field obtained
> by reflection.

OK, I'm not so good at not doing things I say will be 8 lines.  This is
not entirely complete but see how it goes.  It does pass the amazing 1
test suite.

object Ref {
 import java.lang.reflect.{ Type => JType, Array => _, _ }
 import scala.reflect.Manifest.{ classType, intersectionType, arrayType, wildcardType }

 def intersect(tps: JType*): Manifest[_] = intersectionType(tps map javaType: _*)
 def javaType(tp: JType): Manifest[_] = tp match {
   case x: Class[_]            => classType(x)
   case x: ParameterizedType   =>
     val owner = x.getOwnerType
     val raw   = x.getRawType() match { case clazz: Class[_] => clazz }
     val targs = x.getActualTypeArguments() map javaType

     (owner == null, targs.isEmpty) match {
       case (true, true)   => javaType(raw)
       case (true, false)  => classType(raw, targs.head, targs.tail: _*)
       case (false, _)     => classType(javaType(owner), raw, targs: _*)
     }
   case x: GenericArrayType    => arrayType(javaType(x.getGenericComponentType))
   case x: WildcardType        => wildcardType(intersect(x.getLowerBounds: _*), intersect(x.getUpperBounds: _*))
   case x: TypeVariable[_]     => intersect(x.getBounds(): _*)
 }
}

object Test {
 import Ref._
 class MappyDo extends java.util.HashMap[String, String] { }

 def main(args: Array[String]): Unit = {
   val m1 = javaType(classOf[MappyDo].getGenericSuperclass)
   val m2 = manifest[java.util.HashMap[String, String]]

   assert(m1 == m2)
 }
}

--
Paul Phillips      | On two occasions, I have been asked, 'Mr. Babbage, if you
Moral Alien        | put into the machine wrong figures, will the right answers
Empiricist         | come out?' I am not able to rightly apprehend the kind of
slap pi uphill!    | confusion of ideas that could provoke such a question.

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 5 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type
Love it :)
The only catch is, you're picking up on the java signature and not the scala signature, so reflected primitives get all messed up:
scala> class MappyDo extends java.util.HashMap[Int, Double] { }defined class MappyDo
scala>  javaType(classOf[MappyDo].getGenericSuperclass) res7: scala.reflect.Manifest[_] = java.util.HashMap[java.lang.Integer, java.lang.Double]

Still not sure how to deal with that one.I also looked into doing the equivalent with the scala sig and scalap (thanks for the bug fix btw)
This approach has its own problems though:
  • I suspect getting the raw bytes of a class to parse for the scalasig annotation wouldn't work in some security models
    though this mostly looks the be a backward-compatibility thing for the old-style signature, so not a show-stopper.

  • aliased types (such as Seq in Predef) get to be interesting, as they can't themselves be looked-up via Java reflection

On 8 August 2010 06:52, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Sat, Aug 07, 2010 at 07:54:23PM -0300, Germán Ferrari wrote:
> It's possible to get the convertion mentioned in the subject? I'm
> looking for a way to get a Manifest for the type of a field obtained
> by reflection.

OK, I'm not so good at not doing things I say will be 8 lines.  This is
not entirely complete but see how it goes.  It does pass the amazing 1
test suite.

object Ref {
 import java.lang.reflect.{ Type => JType, Array => _, _ }
 import scala.reflect.Manifest.{ classType, intersectionType, arrayType, wildcardType }

 def intersect(tps: JType*): Manifest[_] = intersectionType(tps map javaType: _*)
 def javaType(tp: JType): Manifest[_] = tp match {
   case x: Class[_]            => classType(x)
   case x: ParameterizedType   =>
     val owner = x.getOwnerType
     val raw   = x.getRawType() match { case clazz: Class[_] => clazz }
     val targs = x.getActualTypeArguments() map javaType

     (owner == null, targs.isEmpty) match {
       case (true, true)   => javaType(raw)
       case (true, false)  => classType(raw, targs.head, targs.tail: _*)
       case (false, _)     => classType(javaType(owner), raw, targs: _*)
     }
   case x: GenericArrayType    => arrayType(javaType(x.getGenericComponentType))
   case x: WildcardType        => wildcardType(intersect(x.getLowerBounds: _*), intersect(x.getUpperBounds: _*))
   case x: TypeVariable[_]     => intersect(x.getBounds(): _*)
 }
}

object Test {
 import Ref._
 class MappyDo extends java.util.HashMap[String, String] { }

 def main(args: Array[String]): Unit = {
   val m1 = javaType(classOf[MappyDo].getGenericSuperclass)
   val m2 = manifest[java.util.HashMap[String, String]]

   assert(m1 == m2)
 }
}

--
Paul Phillips      | On two occasions, I have been asked, 'Mr. Babbage, if you
Moral Alien        | put into the machine wrong figures, will the right answers
Empiricist         | come out?' I am not able to rightly apprehend the kind of
slap pi uphill!    | confusion of ideas that could provoke such a question.



--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] gmail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 5 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type
Any objections to seeing this code end up in scalaj-spring?Once I've fleshed out the "not entirely complete" parts of course... :)

On 8 August 2010 06:52, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Sat, Aug 07, 2010 at 07:54:23PM -0300, Germán Ferrari wrote:
> It's possible to get the convertion mentioned in the subject? I'm
> looking for a way to get a Manifest for the type of a field obtained
> by reflection.

OK, I'm not so good at not doing things I say will be 8 lines.  This is
not entirely complete but see how it goes.  It does pass the amazing 1
test suite.

object Ref {
 import java.lang.reflect.{ Type => JType, Array => _, _ }
 import scala.reflect.Manifest.{ classType, intersectionType, arrayType, wildcardType }

 def intersect(tps: JType*): Manifest[_] = intersectionType(tps map javaType: _*)
 def javaType(tp: JType): Manifest[_] = tp match {
   case x: Class[_]            => classType(x)
   case x: ParameterizedType   =>
     val owner = x.getOwnerType
     val raw   = x.getRawType() match { case clazz: Class[_] => clazz }
     val targs = x.getActualTypeArguments() map javaType

     (owner == null, targs.isEmpty) match {
       case (true, true)   => javaType(raw)
       case (true, false)  => classType(raw, targs.head, targs.tail: _*)
       case (false, _)     => classType(javaType(owner), raw, targs: _*)
     }
   case x: GenericArrayType    => arrayType(javaType(x.getGenericComponentType))
   case x: WildcardType        => wildcardType(intersect(x.getLowerBounds: _*), intersect(x.getUpperBounds: _*))
   case x: TypeVariable[_]     => intersect(x.getBounds(): _*)
 }
}

object Test {
 import Ref._
 class MappyDo extends java.util.HashMap[String, String] { }

 def main(args: Array[String]): Unit = {
   val m1 = javaType(classOf[MappyDo].getGenericSuperclass)
   val m2 = manifest[java.util.HashMap[String, String]]

   assert(m1 == m2)
 }
}

--
Paul Phillips      | On two occasions, I have been asked, 'Mr. Babbage, if you
Moral Alien        | put into the machine wrong figures, will the right answers
Empiricist         | come out?' I am not able to rightly apprehend the kind of
slap pi uphill!    | confusion of ideas that could provoke such a question.



--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] gmail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type

On Thu, Aug 12, 2010 at 08:13:43PM +0100, Kevin Wright wrote:
> Any objections to seeing this code end up in scalaj-spring? Once I've
> fleshed out the "not entirely complete" parts of course... :)

You can always use my code for whatever you want.

(Hedge: blanket permission revocable on a going-forward basis.)

(Hedge clipper: no expectation to ever invoke hedge.)

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 5 days ago.
Re: Get scala.reflect.Manifest[_] from java.lang.reflect.Type
Right you are then...
I'm still hopeful about doing something with the ScalaSigBut that route pretty much demands building an entire Scala reflection library; and others before me have already postponed *that* particular chestnut!
One day though, eh?  A lad's entitled to dream :)


On 12 August 2010 21:55, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Thu, Aug 12, 2010 at 08:13:43PM +0100, Kevin Wright wrote:
> Any objections to seeing this code end up in scalaj-spring? Once I've
> fleshed out the "not entirely complete" parts of course... :)

You can always use my code for whatever you want.

(Hedge: blanket permission revocable on a going-forward basis.)

(Hedge clipper: no expectation to ever invoke hedge.)

--
Paul Phillips      | We must respect the other fellow's religion, but only
Protagonist        | in the sense and to the extent that we respect his
Empiricist         | theory that his wife is beautiful and his children smart.
slap pi uphill!    |     -- H. L. Mencken



--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] gmail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland