包名

当你在groovy中定义类的时候需要指定包名,这和java中类似不多介绍。

导入

groovy中的导入也跟java类似,有一下五种:

默认导入

groovy默认导入了一下几个包和类:

import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal

普通导入

普通导入即全类名导入

// importing the class MarkupBuilder
import groovy.xml.MarkupBuilder // using the imported class to create an object
def xml = new MarkupBuilder() assert xml != null

包导入

这个也不用多说

import groovy.xml.*

def markupBuilder = new MarkupBuilder()

assert markupBuilder != null

assert new StreamingMarkupBuilder() != null

静态导入

import static java.lang.String.format 

class SomeClass {

    String format(Integer i) {
i.toString()
} static void main(String[] args) {
assert format('String') == 'String'
assert new SomeClass().format(Integer.valueOf(1)) == '1'
}
}

静态简称导入

静态简称导入在java中是没有的,这里解释一下。Calendar有一个静态方法getInstance()可以获得Calendar的实例,既然是静态方法我们就可以使用上面的静态导入来直接调用getInstance()方法,但getInstance()这个方法在被调用的时候有误导性,不清楚的还以为是用于获得当前类的实例,所以这时候静态简称导入就发挥作用了:

import static Calendar.getInstance as now

assert now().class == Calendar.getInstance().class

这样我们就直接可以调用now()来获得Calendar的实例了,这样是不是清晰了很多?

脚本和类

读了Groovy基本句法应该了解groovy是可以同时支持编写脚本和类的,接下来就来学习一下他们之间的关系。

先看下面的例子

class Main {
static void main(String... args) {
println 'Groovy world!'
}
}

这是java的传统写法,这里把需要执行的代码写在了main中,在groovy中达到同样的效果就简单多了:

println 'Groovy world!'

虽然上面的是一行脚本语言,但在运行的时候Groovy还是将其转换成类来处理,类似如下的类:

Main.groovy

import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {
def run() {
println 'Groovy world!'
}
static void main(String[] args) {
InvokerHelper.runScript(Main, args)
}
}

可以看出来需要执行的代码被放入了run()方法中。

这里我们可以简单证实一下上面的说法:

首先新建一个main.groovy的脚本文件,内容如下:

println 'hello world !'

接着时候groovyc命令将main.groovy转换成字节码main.class,接着使用class文件的阅读工具查看其内容如下:

	//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite; public class main extends Script {
public main() {
CallSite[] var1 = $getCallSiteArray();
} public main(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
} public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, main.class, args);
} public Object run() {
CallSite[] var1 = $getCallSiteArray();
return var1[1].callCurrent(this, "hello world !");
}
}

虽然生成的和上面略有不同,但的确是被转换为一个继承Script的类,而且需要运行的代码被放在run方法中了。

接下来我们看看脚本中定义的方法会被怎么转换。

method.groovy

println 'Hello'

int power(int n) { 2**n }

println "2^6==${power(6)}"

还是按照之前的转换方法,得到结果:

public class method extends Script {
public method() {
CallSite[] var1 = $getCallSiteArray();
} public method(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
} public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, method.class, args);
} public Object run() {
CallSite[] var1 = $getCallSiteArray();
var1[1].callCurrent(this, "Hello");
return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()?var1[4].callCurrent(this, new GStringImpl(new Object[]{Integer.valueOf(this.power(6))}, new String[]{"2^6==", ""})):var1[2].callCurrent(this, new GStringImpl(new Object[]{var1[3].callCurrent(this, Integer.valueOf(6))}, new String[]{"2^6==", ""}));
} public int power(int n) {
CallSite[] var2 = $getCallSiteArray();
return DefaultTypeTransformation.intUnbox(var2[5].call(Integer.valueOf(2), Integer.valueOf(n)));
}
}

可以看到power()被定义在了method这个类中。

下来再来看看变量是怎么被转换的

variables1.groovy

int x = 1
int y = 2
assert x+y == 3

转换结构如下:

public class variables1 extends Script {
public variables1() {
CallSite[] var1 = $getCallSiteArray();
} public variables1(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
} public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, variables1.class, args);
} public Object run() {
CallSite[] var1 = $getCallSiteArray();
byte x = 2;
byte y = 3;
return BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()?var1[3].callCurrent(this, Integer.valueOf(x + y)):var1[1].callCurrent(this, var1[2].call(Integer.valueOf(x), Integer.valueOf(y)));
}
}

可以看出来x,y被定义为了run方法的布局变量。

接着看:

variables2.groovy

x = 2
y = 3
println x+y

转换结果如下

public class variables2 extends Script {
public variables2() {
CallSite[] var1 = $getCallSiteArray();
} public variables2(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
} public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, variables2.class, args);
} public Object run() {
CallSite[] var1 = $getCallSiteArray();
byte var2 = 2;
ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var2), variables2.class, this, (String)"x");
byte var3 = 3;
ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var3), variables2.class, this, (String)"y");
return var1[1].callCurrent(this, var1[2].call(var1[3].callGroovyObjectGetProperty(this), var1[4].callGroovyObjectGetProperty(this)));
}
}

额,看不太懂了,但可以肯定x,y没有被定义成run的成员变量。

综合上面的两个变量转换的例子,请判断下面这个脚本可以正确执行吗?

int x = 1;

def getDoubleX(){
x*2 ;
} println getDoubleX()

答案是不能,这里的x会被定义成run的成员变量,而getDouble这个方法是访问不到x的,这里需要注意。

以上就是关于Groovy中脚本和类的关系了,更多详细内容请参考:

Groovy中的脚本与类的更多相关文章

  1. [SignalR]在非Hub继承类中使用脚本方法

    原文:[SignalR]在非Hub继承类中使用脚本方法 新建一个普通类OutHub,里面包含一个脚本方法OutHubTest. 因为大家知道,若能让脚本调用到的话,必须继承Hub,那怎么实现了?通过G ...

  2. unity3D 中的C#脚本一个类调用另一类中简单方法

    案例展示 SubMenuManage类中的实例化代码如下: static SubMenuManage sub_this; public static SubMenuManage Instance() ...

  3. Groovy中那些神奇注解之Memoized

    临近年关手头比较闲,去看了一下Groovy的官方文档,才发现原来Groovy中带了那么多的注解,很多注解带来的效果,有时候让人感觉“这不是在变魔法吧”. 个人很喜欢Groovy,写不成Ruby,Gro ...

  4. Groovy中的面向对象

    Groovy中的面向对象 前面说到groovy支持脚本和类,前面一节已将简单说了脚本和类之间的关系,这一节主要介绍一下groovy中类的相关知识,即面向对象相关知识. 1.类型 1.1 原始类型 gr ...

  5. 第四章 在MVC4.0中对脚本以及样式表的引用变化

    原文:http://www.cnblogs.com/xdotnet/archive/2012/07/21/aspnet40_webpage20.html 一.可以直接使用“~”,而无需使用Href对象 ...

  6. [Unity2D]脚本基类MonoBehaviour介绍

    Unity中的脚本都是继承自MonoBehaviour. MonoBehaviour 表示一个单一的行为.Unity中用户对游戏对象的操作被分割成若干个单一行为.每个单一行为都作为一个MonoBeha ...

  7. [原]Sql脚本压缩类。

    精简的美丽 /* * Sql脚本压缩类. * 去掉sql语句中多余的空格,以减少sql脚本的文本长度 * * Author : goldli@163.com * DateTime : 2015/07/ ...

  8. Groovy中那些神奇注解之ToString

    继续上一篇:Groovy中那些神奇注解之Memoized 这篇就讲讲@groovy.transform.ToString这个注解,这注解太熟悉了,熟悉到让人一看就知道是干吗的,不就是把Bean转在St ...

  9. groovy中的正则表达式操作符【groovy】

    groovy中对于正则表达式的书写进行了简化,同时引入了新的操作符,使得正则表达式使用起来比较方便简单. 对于书写的改进: 比如 assert "\\d" == /\d/ 也就是在 ...

随机推荐

  1. [转]IIS6 伪静态 IIS文件类型映射配置方法 【图解】

    1.右键点击 要设置网站的网站 2.属性 -->主目录 -->配置--> 3.如右侧窗口,找到 .aspx 扩展名-->编辑-->复制 可执行文件的路径-->关闭 ...

  2. SQL命令查看Mysql数据库大小

    SQL命令查看Mysql数据库大小的方法. 要想知道每个数据库的大小的话,步骤如下:1.进入information_schema 数据库(存放了其他的数据库的信息)use information_sc ...

  3. 架构设计--用户端全http参数接口详细说明v1

    1. 用户端全http参数接口详细说明v1.doc 1 2. change histor 1 3. 接口通用参数说明 1 4. 函数注册接口(规划中) 3 5. 用户权限模块 3 5.1. 用户注册接 ...

  4. 基于Redis实现延时队列服务

    背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单 b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论 c.点我达 ...

  5. 彻底解决_OBJC_CLASS_$_某文件名", referenced from:问题(转)

    PS: 本文为转载而来,如有冲突,请与我联系,将立即删除. 最近在使用静态库时,总是出现这个问题.下面总结一下我得解决方法: 1. .m文件没有导入   在Build Phases里的Compile ...

  6. 数字集成电路设计-14-DPI

    引言 在进行IC验证时,尤其是规模较大的时候,单纯用Verilog和SV来构建testbench.可能会稍显吃力. 在这样的情况下,使用C或者C++等软件语言往往会大大加快验证速度,提高验证效率. P ...

  7. [uboot]uboot如何引导系统

    转自:http://bbs.elecfans.com/jishu_455028_1_1.html 如6410的bootcmd和bootargs默认存在于uboot1.1.6/include/confi ...

  8. centos7系统根目录扩容

    比如 点击了后 点击创建虚拟磁盘 选择一个 20G  然后启动虚拟机使用fdisk查看所有的磁盘 看是否新增了一个20G的硬盘 [root@localhost ~]# fdisk -l 磁盘 /dev ...

  9. centos7 /etc/rc.local需要chmod +x /etc/rc.d/rc.local

    Centos 7.0设置/etc/rc.local无效问题解决 安装centos7以后按照以往习惯修改rc.local添加开机启动命令,但重启后发现无效,再次重启发现依然如故 检查系统rc.local ...

  10. 在后台运行Python脚本服务

    在服务器,程序都是后台运行的,当写的python脚本时,需要:   你要是想python robot.py & 是不行的,一旦用户登出,脚本就自动退出了.用at, cron也可以实现不过我发现 ...