为什么@specialized注释不适用于asInstanceOf? [英] Why @specialized annotation doesn't work for asInstanceOf?

查看:137
本文介绍了为什么@specialized注释不适用于asInstanceOf?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解, @specialized 注解应该为我提到的每种基本类型生成一些unboxed代码,但这不起作用:

  scala> def aaa [@specialized(Int,Double,Float,Long)T] =(5.0).doubleValue.asInstanceOf [T] 
aaa:[T] => T

scala> aaa [Int]
不可恢复的错误(解释器/编译器内)

p>

  scala> def aaa [@specialized(Int,Double,Float,Long)T](a:T)=(5.0).doubleValue.asInstanceOf [T] 
aaa:[T] => T

scala> aaa [Int](0)
ClassCastException

但它仍然使用盒装类型asInstanceOf [ T]。这显然有效:

  scala> (5.0).asInstanceOf [Int] 
res28:Int = 5

更新:
键入擦除和类似的答案编写一个通用的演员功能Scala 没有任何东西处理我的问题。类型擦除只是防止编译器为泛型添加 typecast 字节码操作,但最终会添加 - 请参阅 ClassCastException (由此操作生成)在我的REPL中

解决方案

该方法是专门化的,但在单独编译(即不同的行)下,

在下面的例子中, bBf 可以工作, cBf 已损坏。

  $ scala -Xprint:typer,cleanup 

阶> :pa -raw
//进入粘贴模式(ctrl-D完成)

package a {object A {def aaa [@specialized(Int)T] =(5.0).doubleValue .asInstanceOf [T]}}
package b {object B {def f = aAaaa [Int]}}

//退出粘贴模式,现在解释。

[[typer结尾的语法树]] //< pastie>
包<空> {
package a {
object A extends scala.AnyRef {
def< init>():a.A.type = {
A.super。< init>();
()
};
def aaa [@specialized(scala.Int)T]:T = scala.this.Predef.double2Double(5.0).doubleValue()。asInstanceOf [T]
}
};
package b {
object B extends scala.AnyRef {
def< init>():b.B.type = {
B.super。< init>();
()
};
def f:Int = aAaaa [Int]
}
}
}

[[清理结束时的语法树]] //< ; pastie>
包<空> {
package a {
object A extends object {
def aaa():Object = scala.Double.box(scala.this.Predef.double2Double(5.0).doubleValue());
<专业> def aaa $ mIc $ sp():Int = scala.this.Predef.double2Double(5.0).doubleValue()。toInt();
def< init>():a.A.type = {
A.super。< init>();
()
}
}
};
package b {
object B extends Object {
def f():Int = a.A.aaa $ mIc $ sp();
def< init>():b.B.type = {
B.super。< init>();
()
}
}
}
}


scala> :pa -raw
//进入粘贴模式(ctrl-D完成)

package c {object B {def f = aAaaa [Int]}}

//退出粘贴模式,现在解释。

[[typer结尾的语法树]] //< pastie>
package c {
object B extends scala.AnyRef {
def< init>():c.B.type = {
B.super。< init>();
()
};
def f:Int = a.A.aaa [Int]
}
}

[[清理结束时的语法树]] //< pastie>
package c {
object B extends Object {
def f():Int = scala.Int.unbox(a.A.aaa());
def< init>():c.B.type = {
B.super。< init>();
()
}
}
}


As far as i understand, @specialized annotation should generate some unboxed code for every primitive type i mentioned, but this doesn't work:

scala> def aaa[@specialized(Int, Double, Float, Long) T] = (5.0).doubleValue.asInstanceOf[T]
aaa: [T]=> T

scala> aaa[Int]
unrecoverable error (inside interpreter/compiler)

This compiles:

scala> def aaa[@specialized(Int, Double, Float, Long) T](a: T) = (5.0).doubleValue.asInstanceOf[T]
aaa: [T]=> T

scala> aaa[Int](0)
ClassCastException

But it still uses boxed type for asInstanceOf[T]. This obviously works:

scala> (5.0).asInstanceOf[Int]
res28: Int = 5

UPDATE: Type erasure and answers like that Writing a generic cast function Scala has nothing to do with my problem. Type erasure just preventing compiler from adding typecast byte-code operation for generics, but eventually it will be added - see ClassCastException (generated by this op) in my REPL

解决方案

The method is specialized, but under separate compilation (i.e., different lines), the specialized method isn't invoked.

In the following, b.B.f works, c.B.f is broken.

$ scala -Xprint:typer,cleanup

scala> :pa -raw
// Entering paste mode (ctrl-D to finish)

package a { object A { def aaa[@specialized(Int) T] = (5.0).doubleValue.asInstanceOf[T] }}
package b { object B { def f = a.A.aaa[Int] }}

// Exiting paste mode, now interpreting.

[[syntax trees at end of                     typer]] // <pastie>
package <empty> {
  package a {
    object A extends scala.AnyRef {
      def <init>(): a.A.type = {
        A.super.<init>();
        ()
      };
      def aaa[@specialized(scala.Int) T]: T = scala.this.Predef.double2Double(5.0).doubleValue().asInstanceOf[T]
    }
  };
  package b {
    object B extends scala.AnyRef {
      def <init>(): b.B.type = {
        B.super.<init>();
        ()
      };
      def f: Int = a.A.aaa[Int]
    }
  }
}

[[syntax trees at end of                   cleanup]] // <pastie>
package <empty> {
  package a {
    object A extends Object {
      def aaa(): Object = scala.Double.box(scala.this.Predef.double2Double(5.0).doubleValue());
      <specialized> def aaa$mIc$sp(): Int = scala.this.Predef.double2Double(5.0).doubleValue().toInt();
      def <init>(): a.A.type = {
        A.super.<init>();
        ()
      }
    }
  };
  package b {
    object B extends Object {
      def f(): Int = a.A.aaa$mIc$sp();
      def <init>(): b.B.type = {
        B.super.<init>();
        ()
      }
    }
  }
}


scala> :pa -raw
// Entering paste mode (ctrl-D to finish)

package c { object B { def f = a.A.aaa[Int] }}

// Exiting paste mode, now interpreting.

[[syntax trees at end of                     typer]] // <pastie>
package c {
  object B extends scala.AnyRef {
    def <init>(): c.B.type = {
      B.super.<init>();
      ()
    };
    def f: Int = a.A.aaa[Int]
  }
}

[[syntax trees at end of                   cleanup]] // <pastie>
package c {
  object B extends Object {
    def f(): Int = scala.Int.unbox(a.A.aaa());
    def <init>(): c.B.type = {
      B.super.<init>();
      ()
    }
  }
}

这篇关于为什么@specialized注释不适用于asInstanceOf?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆