我观察到奇怪的行为,在干净的"测试"应用程序我有这个简单的控制器:
(Grails 2.5.0,Java Oracle 8u45,GNU / Linux Debian 7)
package test
class DiController {
def ok() {
double d = 0d
int i = (int)d
def r = []
r << i
if (true) {
r << i
}
else {
r << d
}
if (false) {
r << i
}
else {
r << d
}
render r.toString()
}
def bug() {
double d = 0d
int i = (int)d
def r = []
r << i
r << (true ? i : d) // why Integer will be serialized like Double ?
r << (false ? i : d)
render r.toString()
}
}
/ test / di / ok呈现[0, 0, 0.0]
,但/ test / di / bug呈现[0, 0.0, 0.0]
。
似乎三元运算符转换结果值,但我还没有在Groovy控制台中观察到这种转换。这个Grails具体吗?
(Graeme Rocher将此标记为&#34;不是错误&#34;此处:https://github.com/grails/grails-core/issues/8994,因此应该知道行为)
编辑:我使用较旧的Groovy(1.8.6)进行测试&#34;出于Grails&#34;,Groovy 2.4.3描述了行为(给出了[0, 0.0, 0.0]
),所以它与Grails无关。
答案 0 :(得分:0)
我相信这是因为Groovy试图找到不兼容类型的共同点。这是各种三元运算符使用的一个例子:
println ((true ? (0 as Integer) : (0.0 as Float)).class)
println ((true ? (0 as Float) : (0.0 as Double)).class)
println ((true ? (0 as Integer) : (0 as Long)).class)
println ((true ? (0 as Integer) : (0 as Byte)).class)
这就是Groovy如何将其编译成Java
var1[1].callCurrent(this, var1[2].callGetProperty(true?(Float)ScriptBytecodeAdapter.castToType((Integer)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Integer.class), Float.class):(Float)ScriptBytecodeAdapter.asType($const$0, Float.class)));
var1[3].callCurrent(this, var1[4].callGetProperty(true?(Double)ScriptBytecodeAdapter.castToType((Float)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Float.class), Double.class):(Double)ScriptBytecodeAdapter.asType($const$0, Double.class)));
var1[5].callCurrent(this, var1[6].callGetProperty(true?(Long)ScriptBytecodeAdapter.castToType((Integer)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Integer.class), Long.class):(Long)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Long.class)));
var1[7].callCurrent(this, var1[8].callGetProperty(true?(Integer)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Integer.class):(Integer)ScriptBytecodeAdapter.castToType((Byte)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Byte.class), Integer.class)));
在所有情况下,它执行大量类型转换只是为了同意true / false结果分支并使它们返回相同的类型。令人惊讶的是,这仅适用于数值。其他值的处理方式也不同。
println ((true ? ("s") : (0 as Byte)).class)
println ((false ? ("s") : (0 as Byte)).class)
println ((true ? (new Date()) : (0 as Byte)).class)
像
一样被翻译成Javavar1[9].callCurrent(this, var1[10].callGetProperty(true?"s":(Byte)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Byte.class)));
var1[11].callCurrent(this, var1[12].callGetProperty(false?"s":(Byte)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Byte.class)));
var1[13].callCurrent(this, var1[14].callGetProperty(true?var1[15].callConstructor(Date.class):(Byte)ScriptBytecodeAdapter.asType(Integer.valueOf(0), Byte.class)));
它没有回答为什么,但回答 发生了什么。至少我希望如此。