Scala ที่เทียบเท่ากับวัตถุ Java java.lang.Class <T>


183

ตัวอย่างคำถามอธิบายได้ดีที่สุดโดย:

ใน Java สำหรับ JPA EntityManager ฉันสามารถทำสิ่งต่อไปนี้ได้ (บัญชีคือคลาส Entity ของฉัน):

Account result = manager.find(Account.class, primaryKey);

ใน Scala ความพยายามที่ไร้เดียงสาของฉันคือ:

val result = manager.find(Account.class, primaryKey)

แต่เมื่อฉันลองใช้Account.classใน Scala ดูเหมือนว่าจะไม่เป็นแบบนี้ ฉันจะระบุวัตถุ java.lang.Class สำหรับคลาสบัญชีใน Scala ได้อย่างไร


VonC ได้ให้คำตอบแล้ว แต่ดูคำถาม / คำตอบของฉันเองเกี่ยวกับ Scala & Erasure ฉันคิดว่ามันอาจช่วยให้คุณมีความคิดที่จะทำสิ่งที่แตกต่างจากสิ่งที่คุณพยายาม
Daniel C. Sobral

คำตอบ:


264

ตามที่ " ระบบประเภทสกาล่า "

val c = new C
val clazz = c.getClass              // method from java.lang.Object
val clazz2 = classOf[C]             // Scala method: classOf[C] ~ C.class
val methods = clazz.getMethods      // method from java.lang.Class<T>

classOf[T]วิธีการส่งกลับเป็นตัวแทนรันไทม์สำหรับชนิดสกาล่า T.classมันจะคล้ายคลึงกับการแสดงออก Java
การใช้classOf[T]สะดวกเมื่อคุณมีประเภทที่คุณต้องการข้อมูลในขณะที่getClassสะดวกในการดึงข้อมูลเดียวกันจากอินสแตนซ์ของประเภท

อย่างไรก็ตามclassOf[T]และgetClassส่งคืนค่าที่แตกต่างกันเล็กน้อยซึ่งสะท้อนถึงผลกระทบของการลบประเภทใน JVM ในกรณีของ getClass

scala> classOf[C]
res0: java.lang.Class[C] = class C

scala> c.getClass
res1: java.lang.Class[_] = class C

นั่นคือเหตุผลที่ต่อไปนี้จะไม่ทำงาน :

val xClass: Class[X] = new X().getClass //it returns Class[_], nor Class[X]

val integerClass: Class[Integer] = new Integer(5).getClass //similar error

มีความเป็นตั๋วเกี่ยวกับประเภทการกลับมาของgetClass

( James Mooreรายงานว่าตั๋วเป็น "ตอนนี้" คือพฤศจิกายน 2011 สองปีต่อมาคงที่
ใน 2.9.1 getClassตอนนี้จะ:

scala> "foo".getClass 
       res0: java.lang.Class[_ <: java.lang.String] = class java.lang.String

)

ย้อนกลับไปในปี 2009:

มันจะมีประโยชน์ถ้าสกาล่าจะรักษาผลตอบแทนจาก getClass () เป็น java.lang.Class [T] forSome {val T: C} โดยที่ C เป็นสิ่งที่ต้องการลบประเภทคงที่ของการแสดงออกที่ getClass เป็น เรียกว่า

มันจะให้ฉันทำสิ่งต่อไปนี้ที่ฉันต้องการวิปัสสนาในชั้นเรียน แต่ไม่ควรต้องการอินสแตนซ์ของคลาส
ฉันต้องการ จำกัด ประเภทของคลาสที่ฉันต้องการจะใคร่ครวญด้วยดังนั้นฉันจึงใช้ Class [_ <: Foo] แต่สิ่งนี้ทำให้ฉันไม่สามารถผ่านคลาส Foo ได้โดยใช้ Foo.getClass () โดยไม่ต้องส่ง

หมายเหตุ: เกี่ยวกับgetClassวิธีแก้ปัญหาที่เป็นไปได้คือ:

class NiceObject[T <: AnyRef](x : T) {
  def niceClass : Class[_ <: T] = x.getClass.asInstanceOf[Class[T]]
}

implicit def toNiceObject[T <: AnyRef](x : T) = new NiceObject(x)

scala> "Hello world".niceClass                                       
res11: java.lang.Class[_ <: java.lang.String] = class java.lang.String

4
FYI, ตั๋ว @VonC ที่กล่าวถึงถูกทำเครื่องหมายไว้ในวันที่ 22 / Jun / 11 ใน 2.9.1 ตอนนี้ getClass ทำเช่นนี้: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = คลาส java.lang.String
James Moore

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.