如何获取对象的类型并将其传递给Scala中的asInstanceOf?

时间:2013-11-23 20:57:50

标签: scala scala-2.10

我有一个Scala类,它读取JOSN模板文件中的格式信息,以及来自不同文件的数据。目标是格式化为模板文件指定的JSON对象。我正在使布局工作,但现在我想将输出的类型设置为我的模板中的类型(即如果我在模板中有一个字段值作为字符串,它应该是输出中的字符串,甚至如果它是原始数据中的整数)。

基本上,我正在寻找一种快速简便的方法:

output = dataValue.asInstanceOf[templateValue.getClass]

该行给出了一个错误,即类型getClass不是Any的成员。但我还没有找到任何其他成员或方法在运行时给我一个变量类型。这是可能的,如果是的话,怎么样?

澄清

我应该在我的代码中添加,我知道我只处理一个键/值对。我想要的是价值的类型。

具体来说,给定下面的JSON模板,我希望将名称转换为String,将age转换为整数,并将输出的工资转换为输出小数,而不管它在原始数据文件中的显示方式(它可以是所有字符串,年龄和工资都可以是整数,等等。我希望的是一个简单的强制转换,它不需要我进行模式匹配来专门处理每种数据类型。

示例模板:

people: [{  
    name: "value",  
    age: 0,  
    salary: 0.00  
}]

3 个答案:

答案 0 :(得分:3)

类型参数必须在编译时知道(类型符号),而templateValue.getClass只是一个普通值(类型为Class),因此它不能用作类型参数。 该怎么做 - 这取决于你的目标,这对我来说尚不清楚......但它可能看起来像

output = someMethod(dataValue, templateValue.getClass)

并且在该方法中,您可以根据类型Class的第二个参数进行不同的计算。

答案 1 :(得分:3)

  1. 如何获取对象的类型并将其传递给Scala中的asInstanceOf?

    方法scala.reflect.api.JavaUniverse.typeOf[T]要求调用者或类型推断对其类型参数进行硬编码。要进行类型推断,请创建如下所示的实用程序方法(适用于所有类型,甚至是泛型 - 它通过在使用类型标记元数据进行编译期间扩充T来抵消java运行时类型arg擦除):

    // http://www.scala-lang.org/api/current/index.html#scala.reflect.runtime.package
    import scala.reflect.runtime.universe._   
    def getType[T: TypeTag](a: T): Type = typeOf[T]
    

    这里有3项要求:

    • 类型arg实现TypeTag(但之前通过Manifest实现仍然可用...)
    • 输入一个或多个输入参数T
    • 返回类型是Type(如果您希望结果在方法外部使用)

    您可以在不指定T(它是类型推断)的情况下调用:

    import scala.reflect.runtime.universe._
    def getType[T: TypeTag](a: T): Type = typeOf[T]
    val ls = List[Int](1,2,3)
    println(getType(ls))  // prints List[Int]
    

    但是,asInstanceOf只会将类型转换为层次结构中的(二进制一致)类型,而不会转换数据或格式。即数据必须已经采用正确的二进制格式 - 这样才能解决您的问题。

  2. 数据转换

    一些方法在整数和字符串之间进行转换:

    // defined in scala.Any:
    123.toString                  // gives "123"
    // implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
    123.toHexString               // gives "7b"
    123.toOctalString             // gives "173"
    "%d".format(123)              // also gives "123"
    "%5d".format(123)             // gives "  123"
    "%05d".format(123)            // gives "00123"
    "%01.2f".format(123.456789)   // gives "123.46"
    "%01.2f".format(123.456789)   // gives "0.46"
    
    // implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
    "  123".toInt                 // gives 123
    "00123".toInt                 // gives 123
    "00123.4600".toDouble         // gives 123.46
    ".46".toDouble                // gives 0.46
    
  3. 直接从文件解析到目标类型(无投射或转换):

    不幸的是,scala没有一种方法来读取流中的下一个标记为整数/浮点数/短/布尔/等。但是你可以通过获取java FileInputStream,将其包裹在DataInputStream然后调用readIntreadFloatreadShortreadBoolean来实现等等

答案 2 :(得分:0)

在类型级别上下文中,值级别的术语仍然具有一些访问器。第一个和您要求的是值本身的类型(type):

output = dataValue.asInstanceOf[templateValue.type]

如果值的类型具有内部成员,那么它们也可用:

class A {
  class B {}
}

val a: A = new A
val b: a.B = new a.B

注意b: a.B

我还必须提到如何在没有价值级术语的情况下访问这些成员:

val b: A#B = new a.B