调试 – 为什么Groovy常量可以递增?

调试 – 为什么Groovy常量可以递增?,第1张

概述在Groovy Console中,(((1)))计算结果为5! 为什么? 我期望一个错误,文字常量不能递增! Pre-Increment给出下一个Integer,而Post-Increment给出相同的Integer,但我希望两者在与文字常量一起使用时抛出错误. [[我在带有Java 1.8.0_101的Groovy 2.4.10的Windows 10上运行]] 好问题,我很想看到一个权威的答案. @H_419_2@ 在Groovy Console中,(((1)))计算结果为5!
为什么?
我期望一个错误,文字常量不能递增!

Pre-Increment给出下一个Integer,而Post-Increment给出相同的Integer,但我希望两者在与文字常量一起使用时抛出错误.

[[我在带有Java 1.8.0_101的Groovy 2.4.10的windows 10上运行]]

解决方法 好问题,我很想看到一个权威的答案.

我在这上面打开了一个标签但仍然没有看到,所以我调查了自己.如果你有耐心阅读,下面是一个简单的Groovy用户(你真正的)的观点,用我拥有的工具和不完整的知识(希望不要太误)来看这个.

简而言之:语言设计&编译器实现更关心功率和功能变革带来的灵活性,这显然是以放松严谨为代价的.

Groovy在设计上非常宽松,有时候可能有点太多了.

> if(condition)int foo = 1被javac拒绝,“此处不允许声明”,因为在那里声明变量没有意义,一定有错误,更好地检查代码,对吧? Naaah对Groovy来说没问题.
>私人领域和方法are not private.
> final是applied inconsistently.您可以增加最终的int.这将在2.5中修复,见下文.

Groovy 2.4和#之间的最终差异处理2.5:

$./groovy-2.4.11/bin/groovy -e "final j=0; println(++j)"1$./groovy-2.5.0-Alpha-1/bin/groovy -e "final j=0; println(++j)"org.codehaus.groovy.control.MultipleCompilationErrorsException: startup Failed:script_from_command_line: 1: The variable [j] is declared final but is reassigned. At [1:20]  @ line 1,column 20.   final j=0; println(++j)                      ^1 error

但不,Groovy 2.5仍然无法阻止增加常量:

$./groovy-2.4.11/bin/groovy -e "println(++1)"2$./groovy-2.5.0-Alpha-1/bin/groovy -e "println(++1)"2

那么1发生了什么?

我认为第一个重要的是Groovy不是Java,它不会转换为Java语言.它编译为字节码. Groovy&amp ;;这里有很大的不同. Java的.

Groovy有9 compilation phases(见org.codehaus.groovy.control.CompilePhase):初始化,解析,转换,语义分析,规范化,指令选择,类生成,输出,终结.

我们可以使用GroovyConsole探索它们.让我们在这个简单的片段上开始吧:

def foo() {    ++1}

我在编译和解析阶段没有看到任何内容,但在转换阶段,我们得到了一些有趣的东西:

public java.lang.Object foo() {    ++(1)}

常数被括号括起来.嗯.有意思,请注意我们可以做(2 2)并得到5.这里没有增量变量……似乎只是一个像incrementThis(thing)这样的方法的快捷方式,它可以增加东西并返回它,或者如果事物是一个常数,它为事物添加1并返回结果.

在我的IDE中,如果我按住Ctrl键单击它,请转到org.codehaus.groovy.runtime.DefaultGroovyMethods.next(Number self):

/** * Increment a Number by one. * * @param self a Number * @return an incremented Number * @since 1.0 */public static Number next(Number self) {    return NumberNumberPlus.plus(self,ONE);}

如果我追踪到这一点,它最终只会做一个自我,所以我不知道自我改变的位置,我认为这不是那么简单.我的意思是(x)不仅仅是DefaultGroovyMethods.next(x)的快捷方式,还有更多.

那么让我们看看如果我分别使用javac和groovyc编译以下内容会发生什么:

//Wat.java:public class Wat {    public int foo() {        int i=1;        return ++i;    }}//wat.groovy:def foo() {  ++1}

这是我得到的(Java 1.8,Groovy 2.4,专注于相关部分):

// Java:0: iconst_1                // load int value 1 onto stack1: istore_1                // store int value into variable #12: iinc          1,1      // increment local variable #1 by 15: iload_1                 // load int value from local variable #16: ireturn                 // return that integer value// Groovy:43: iconst_1               // load int value 1 onto stack44: iconst_1               // load another int value 1 onto stack45: iadd                   // add those 2 ints (result stored on stack in place of first int,stack is popped by 1)46: invokestatic  #58      // Invoke method java/lang/Integer.valueOf(prevIoUs result)49: areturn                // Return that new Integer result

所以对于Groovy 1来说相当于Integer.valueOf(1 1)(而严格性只需要一个后座).

但是def foo(i){i}怎么样?我编译,我显然是一个对象,但我不理解生成的字节码,我仍然没有看到DefaultGroovyMethods.next或NumberNumberPlus.plus的引用.这就是我认为这种分析不足的地方,并希望看到一个权威的答案.

@H_419_2@ 总结

以上是内存溢出为你收集整理的调试 – 为什么Groovy常量可以递增?全部内容,希望文章能够帮你解决调试 – 为什么Groovy常量可以递增?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1234919.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存