簡體   English   中英

在Scala中運行時檢查參數類型(來自可變長度參數列表)

[英]Check argument type (from a variable length argument list) at runtime in Scala

我正在為可以接受應用於給定數據結構的規則的系統設計接口。

主系統應該作為驅動程序接收命令,例如“將規則X應用於參數U,V,W,......”。 我不知道編譯時所有可能的規則,所以我想在規則定義中嵌入參數類型信息並對其進行驗證。

現在規則定義如下:

trait Rule {
  val argTypes: Seq[Class[_]]
  def apply(stt: State, args: Seq[Any])
}

args中實際參數的數量必須與argTypes定義的類型數相匹配,而apply方法應返回操作狀態。 (實際上,這是簡化的解釋,但這是一般的想法)。

我還實現了一個名為checkTypes的函數來驗證實際參數的類型是否與argTypes定義的類型匹配。

def checkTypes(args: Seq[Any]) {
  if (argTypes.size != args.size) {
    val msg = "Number of arguments (%d) does not match expected number (%d)."
    throw new IllegalArgumentException(msg.format(args.size, argTypes.size))
  }
  val err = "Incompatible argument type for [%s]. Expected: %s. Found: %s."
  for (i <- 0 until argTypes.size) {
    val formalClass = argTypes(i)
    val arg = args(i)
    val actualClass = arg.asInstanceOf[AnyRef].getClass
    if (!(formalClass isAssignableFrom actualClass)) {
      val errMsg = err.format(arg, formalClass.getName, actualClass.getName)
      throw new IllegalArgumentException(errMsg)
    }
  }
}

問題是每當我嘗試傳遞整數參數(從控制台或文本文件中讀取)時, checkTypes過程就會失敗,並顯示以下消息: java.lang.IllegalArgumentException: Incompatible argument type for [1]. Expected: int. Found: java.lang.Integer. java.lang.IllegalArgumentException: Incompatible argument type for [1]. Expected: int. Found: java.lang.Integer.

我正在使用Integer.parseInt(t).asInstanceOf[Int]轉換整數參數,並且規則需要兩個Int類型的參數

那么,有沒有更有效的方法來檢查運行時的參數類型?

要么

如何將String轉換為Int實際?

提前致謝。


作為最低工作示例,這是Scala REPL中的一個會話,它會引發異常:

scala> val argTypes: Seq[Class[_]] = Seq(classOf[Int], classOf[Int])
argTypes: Seq[Class[_]] = List(int, int)

scala> def checkTypes(args: Seq[Any]) {
     |   if (argTypes.size != args.size) {
     |     val msg = "Number of arguments (%d) does not match expected number (%d)."
     |     throw new IllegalArgumentException(msg.format(args.size, argTypes.size))
     |   }
     |   val err = "Incompatible argument type for [%s]. Expected: %s. Found: %s."
     |   for (i <- 0 until argTypes.size) {
     |     val formalClass = argTypes(i)
     |     val arg = args(i)
     |     val actualClass = arg.asInstanceOf[AnyRef].getClass
     |     if (!(formalClass isAssignableFrom actualClass)) {
     |       val errMsg = err.format(arg, formalClass.getName, actualClass.getName)
     |       throw new IllegalArgumentException(errMsg)
     |     }
     |   }
     | }
checkTypes: (args: Seq[Any])Unit

scala> val args: Seq[Any] = Seq("1".toInt, "2".toInt)
args: Seq[Any] = List(1, 2)

scala> checkTypes(args)
java.lang.IllegalArgumentException: Incompatible argument type for [1]. Expected: int. Found: java.lang.Integer.
    at $anonfun$checkTypes$1.apply$mcVI$sp(<console>:20)
    at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:78)
    at .checkTypes(<console>:14)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
    at java.lang.Thread.run(Thread.java:679)

盒裝類型( java.lang.Integer )和未裝箱類型( scala.Int == java int )之間不匹配。 實際的實例是盒裝的,但是你要對原始的classOf進行測試。

以下是基元被裝箱時會發生什么的示例:

scala> 5.getClass
res0: Class[Int] = int

scala> (5: Any)
res1: Any = 5

scala> res1.getClass
res2: Class[_] = class java.lang.Integer

請注意,如果您在Any上進行模式匹配並獲得一個原語,它實際上將挑選出盒裝副本並為您取消裝箱。

scala> res1 match { case i: Int => println(i); case _ => }
5

既然你知道你必須裝箱,考慮到你編寫的代碼,你也可以只檢查Integer而不是Int (也就是使用classOf[Integer] )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM