我想這是不可能的,即使宏:
import scala.reflect.macros.Context
import scala.language.experimental.macros
def showMacroImpl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val inputs = annottees.map(_.tree).toList
println(inputs.map{showRaw(_)})
c.Expr[Any](Block(inputs, Literal(Constant(()))))
}
import scala.annotation.StaticAnnotation
class showMacro extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro showMacroImpl
}
object Test {
@showMacro final val i = 1+1
@showMacro final val j = util.Random.nextInt()
@showMacro final val k = Int.MaxValue/2
}
// List(ValDef(Modifiers(FINAL), newTermName("i"), TypeTree(), Apply(Select(Literal(Constant(1)), newTermName("$plus")), List(Literal(Constant(1))))))
// List(ValDef(Modifiers(FINAL), newTermName("j"), TypeTree(), Apply(Select(Select(Ident(newTermName("util")), newTermName("Random")), newTermName("nextInt")), List())))
// List(ValDef(Modifiers(FINAL), newTermName("k"), TypeTree(), Apply(Select(Select(Ident(newTermName("Int")), newTermName("MaxValue")), newTermName("$div")), List(Literal(Constant(2))))))
有i
,j
和k
這裏沒有什麼區別。
你會得到任何信息,即使scalac -Xprint:cleanup test.scala
:
final <stable> <accessor> def i(): Int = 2;
final <stable> <accessor> def j(): Int = Test.this.j;
final <stable> <accessor> def k(): Int = 1073741823;
你只能從.icode
文件中獲取此信息(scalac -Xprint:all test.scala; cat Test\$.icode
):
def i(): Int(2) {
locals:
startBlock: 1
blocks: [1]
1:
2 CONSTANT(2)
2 RETURN(INT)
}
def k(): Int(1073741823) {
locals:
startBlock: 1
blocks: [1]
1:
4 CONSTANT(1073741823)
4 RETURN(INT)
}
或者從Java字節碼(javap -c Test\$.class
):
public final int i();
Code:
0: iconst_2
1: ireturn
public final int k();
Code:
0: ldc #21 // int 1073741823
2: ireturn
1.您可以在這裏使用'val':'@inline val TwentyTwo = 22'。 2.不,它不會使'TwentyTwo'在java字節碼方面保持不變。試試'@inline val j = util.Random.nextInt()' - 它絕對不是編譯時常量。 – senia
是的,謝謝,我想要一個方法來保證它。我正在做一些需要極高性能的大集合的算術密集型工作。所以我想確保編譯時可以訪問該常量的值。 –
很顯然,如果方法體中有參數或副作用,它不會是任何你會稱之爲常量的東西,但我認爲提問者不會這樣做,它會使問題的整個前提無效。 –