Scala转换为泛型类型(用于泛型数值函数)

Scala转换为泛型类型(用于泛型数值函数),scala,generics,casting,scala-java-interop,Scala,Generics,Casting,Scala Java Interop,我试图实现一个封装数学Java函数的通用函数。为了简单起见,我们可以假设Java函数(Java7)接受一个参数并返回一个结果,两种类型都是Java.lang.Double。当然,包装函数应该包含一个参数和一个结果,这两个参数和结果都是泛型的,但都是数字类型a。问题是我无法在包装函数中将结果转换回类型a。哪里出了问题 注:(我是Scala的新手,使用以下参考资料解决了这个问题。) 我使用隐式类型trait Numeric来强制执行模板类型是数值的 我发现了“import scala.collec

我试图实现一个封装数学Java函数的通用函数。为了简单起见,我们可以假设Java函数(Java7)接受一个参数并返回一个结果,两种类型都是Java.lang.Double。当然,包装函数应该包含一个参数和一个结果,这两个参数和结果都是泛型的,但都是数字类型a。问题是我无法在包装函数中将结果转换回类型a。哪里出了问题

注:(我是Scala的新手,使用以下参考资料解决了这个问题。)

  • 我使用隐式类型trait Numeric来强制执行模板类型是数值的
  • 我发现了“import scala.collection.JavaConversions.”,我并不完全理解,但在我看来,这是为了转换Java集合,并不能解决我的问题,是吗
  • 正如这里所描述的,我试图使用Manifest强制执行正确的强制转换(变体B),但最终导致异常java.lang.ClassCastException
变体A “一些代码”A1 输出:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
    at test.mytest$.main(test.scala:10)
    at test.mytest.main(test.scala)
3.0
int
“一些代码”A2 输出:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
    at test.mytest$.main(test.scala:10)
    at test.mytest.main(test.scala)
3.0
int
“一些代码”A3 输出:

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
    at test.mytest$.main(test.scala:10)
    at test.mytest.main(test.scala)
3.0
int
变体B 输出: (对于变体A1、A2和A3的等价物也是如此,因为异常现在在函数f的第6行中抛出。)


无论如何,您不能将
Double
强制转换为
Integer
(因为它已装箱)
Numeric
只允许您在T上进行一组数学运算(通过
import num.
),无需其他操作(不需要中间类型)。A2只起作用,因为println由于
f(3)
而期望
Any
,因此
T
自动推断为
Any
println(f[Int](3))
永远不起作用,
f[Any](3)
永远起作用

如果您想要实现操作Double的泛型函数(只有当您有特定于Double的操作时,才可能需要该函数),那么最好返回Double。如果不能,则必须通过分析t来手动构造类型:

def f[A](x: A)(implicit num: Numeric[A]): A = {
   val result = new java.lang.Double(num.toDouble(x))
   (x match {
       case x: Double => result
       case x: Int => result.toInt
       case x: Float => result.toFloat
       case x: Long => result.toLong
   }).asInstanceOf[A]
}
不能在这里执行[A]的原因是A已经装箱了
@specialized
注释不适用于
的安装()

更新:实际上,
@specialized
工作:

def f[@specialized(Int, Double, Long, Float) A](x: A)(implicit num: Numeric[A]): A = {
   val result = new java.lang.Double(num.toDouble(x)) 

   result.doubleValue.asInstanceOf[A]
}
但是它-所以要小心


p.S.清单不推荐使用:改用
classTag
/
typeTag

是否有可能强制强制强制将双精度转换为整数,如在Java中,例如(int)(1.8)返回1?尽管如此,匹配输入参数对我来说是可行的,但这有点像黑客攻击——从我的角度来看——如果能得到语言本身的支持就好了,因为这样变体B就可以工作了,是吗?非常感谢,对我来说,它现在可以工作了!:)<代码>(1.8)。asInstanceOf[Int]
在scala中工作,但它不适用于盒装类型(即使在Java中),这太棒了!更新后的解决方案现在使用了语言功能,正如我所期望的那样:该解决方案现在是“真正”通用的,因为如果列表为空,前一个解决方案对于函数
def[a](list:list[a])(implicit num:Numeric[a]):a={…}
就不起作用(或者至少需要另一种解决方法)。谢谢+1用于更新的解决方案。