Groovy语法之类
来源:互联网 发布:守望先锋左上角6个数据 编辑:程序博客网 时间:2024/06/10 20:14
概述
groovy与java的class的共性:从分类来看,分为普通类、匿名类、抽象类、接口、匿名内部类;从自定义来看,标识符class、访问限定符(public、protected 、private、static),属性与方法的定义等都非常类似。
访问权限的区别:groovy的class将java中默认访问权限与public等效,即没有指定访问限定符都被当成public来使用。
直接引用属性的区别:groovy的class使用直接引用属性来替代get/set方法,注意直接引用属性实际调用的是对应的get/set方法。
get/set方法生成的区别:groovy的class会自动生成get/set方法,不需要重复提供。如下代码:
class Dog { String name}def dog = new Dog()dog.getName()
Dog编译之后的class:
public class Dog implements GroovyObject { private String name; public Dog() { CallSite[] var1 = $getCallSiteArray(); MetaClass var2 = this.$getStaticMetaClass(); this.metaClass = var2; } public String getName() { return this.name; } public void setName(String var1) { this.name = var1; }}
构造方法
对于提供了构造方法的类,groovy有如下三种方式来实例化该对象:
class Person { String name int age Person(String name, int age) { this.name = name this.age = age } @Override String toString() { return "name=$name, age=$age" }}
void testConstructors() { def obj1 = new Person('jake', 22) println(obj1) def obj2 = ['jake', 22] as Person println(obj2) Person obj3 = ['jake', 22] println(obj3)}
上述三种实例化方式对应的class如下:
public void testConstructors() { CallSite[] var1 = $getCallSiteArray(); Object obj1 = var1[2].callConstructor(Person.class, "jake", Integer.valueOf(22)); var1[3].callCurrent(this, obj1); Object obj2 = (Person)ScriptBytecodeAdapter.asType(ScriptBytecodeAdapter.createList(new Object[]{"jake", Integer.valueOf(22)}), Person.class); var1[4].callCurrent(this, obj2); Person obj3 = (Person)ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.createList(new Object[]{"jake", Integer.valueOf(22)}), Person.class); var1[5].callCurrent(this, obj3);}
由上可知,第一种是直接调用构造方法;第二种则是使用as操作符来完成对象的创建,原理是使用as操作符完成对象实例化;第三种则是直接强转成目标对象的示例,原理是使用list来保存构造方法的参数,然后作为目标对象的参数,最终使用new构造示例,如下:
private static Object continueCastOnSAM(Object object, Class type) { ... ... Object[] args = null; if (object instanceof Collection) { // let's try invoke the constructor with the list as arguments // such as for creating a Dimension, Point, Color etc. Collection collection = (Collection) object; args = collection.toArray(); } else if (object instanceof Object[]) { args = (Object[]) object; } else if (object instanceof Map) { // emulate named params constructor args = new Object[1]; args[0] = object; } ... ... }
对于没有提供了构造方法的类,可以使用如下的几种方式:
class Cat { String name int age}void testNamedArgumentConstructors() { def cat1 = new Cat() println(cat1) def cat2 = new Cat(name: 'Marie') println(cat2) def cat3 = new Cat(age: 1) println(cat3) def cat4 = new Cat(name: 'Marie', age: 2) println(cat4) //def cat5 = ['jake', 22] as Cat //println(cat5) //def cat6 = ['jake', 22] //println(cat6)}
注意:没有构造方法是不能使用前面as操作符或强转来实例化的,再看编译之后的字节码:
public void testNamedArgumentConstructors() { CallSite[] var1 = $getCallSiteArray(); Object cat1 = var1[2].callConstructor(Cat.class); var1[3].callCurrent(this, cat1); Object cat2 = var1[4].callConstructor(Cat.class, ScriptBytecodeAdapter.createMap(new Object[]{"name", "Marie"})); var1[5].callCurrent(this, cat2); Object cat3 = var1[6].callConstructor(Cat.class, ScriptBytecodeAdapter.createMap(new Object[]{"age", Integer.valueOf(1)})); var1[7].callCurrent(this, cat3); Object cat4 = var1[8].callConstructor(Cat.class, ScriptBytecodeAdapter.createMap(new Object[]{"name", "Marie", "age", Integer.valueOf(2)})); var1[9].callCurrent(this, cat4);}
public static Map createMap(Object[] values) { Map answer = new LinkedHashMap(values.length / 2); int i = 0; while (i < values.length - 1) { if ((values[i] instanceof SpreadMap) && (values[i + 1] instanceof Map)) { Map smap = (Map) values[i + 1]; Iterator iter = smap.keySet().iterator(); for (; iter.hasNext();) { Object key = iter.next(); answer.put(key, smap.get(key)); } i += 2; } else { answer.put(values[i++], values[i++]); } } return answer;}
总之,上面通过map来封装构造参数,不再限制构造方法的参数位置与数量,比较灵活。
方法
方法返回类型:指定返回类型或def关键字,编译器会当成object类型返回。如下代码:
def testMethod() { a = 1}
public Object testMethod() { CallSite[] var1 = $getCallSiteArray(); byte var2 = 1; ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var2), Main.class, this, (String)"a"); return Integer.valueOf(var2);}
注意:在方法中没有提供return语句情况下,groovy会以最后被执行的那行代码为依据作为返回值,如上述例子。
与构造方法类似:通过以map作为参数可突破普通方法对参数的限制,如下代码,好处是使得方法更加的灵活通用,不需要提供多个重载方法:
def testMethod(Map args) { println("args:${args}")}testMethod(name: 'jake', age: 22, phone: 123456)
如果在调用方法时提供了默认参数,调用方法时可以不传递有默认值的参数,如下:
def testMethod(String name, int age = 12) { println("name=$name,age=$age")}testMethod('Jake')
实现的原理是groovy编译代码之后会自动生成对应的重载方法,如下:
public Object testMethod(String name, int age) { CallSite[] var3 = $getCallSiteArray(); return var3[2].callCurrent(this, new GStringImpl(new Object[]{name, age}, new String[]{"name=", ",age=", ""}));}public Object testMethod(String name) { CallSite[] var2 = $getCallSiteArray(); return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass() ? this.testMethod(name, 12) : this.testMethod(name, 12);}
不定参数定义有两种:一是与java一样(…)或使用对象数组,两种方式是等效的,如下例子:
def testVarargsArags(Object... args) { args.length}println(testVarargsArags(1, 2, 3))def testAragsArray(Object[] args) { args.length}println(testAragsArray(1, 2, 3))
以下是编译过后的字节码:
public Object testVarargsArags(Object... args) { CallSite[] var2 = $getCallSiteArray(); return var2[5].callGetProperty(args);}public Object testAragsArray(Object... args) { CallSite[] var2 = $getCallSiteArray(); return var2[6].callGetProperty(args);}
字段与属性
Fields:在groovy中将类中的成员变量统称为Fields,组成格式如下:
访问限定符(public..) + 可选修饰符(static…) + 类型(可省略)+ 变量名称注意:groovy建议Fields的类型最好要明确指定,以防止某些应用场景依赖具体类型。
properties:是groovy从Fields中那些被限定private的Fields,并提供了getters/setters方法的统称。
注意:properties是不用提供get/set方法的,因为编译器会自动生成;可以直接使用properties访问对应的get/set方法;声明为final的属性,不会生成对应的set方法。
Groovy直接属性访问不仅限于properties,凡是提供了get/set方法的类都支持,如下javabean示例:
class JavaBean { String getId() { return '111' }}def testProperties() { def bean = new JavaBean() println(bean.id)}
注解
与java的注解类似,groovy注解定义格式:
@interface 注解名 { 类型 成员方法名() 默认值}
类型被限制在:基本类型、String、Class、枚举、注解类型或这些类型的数组类型,如下示例:
@interface SomeAnnotation { String value()}@interface SomeAnnotation { String value() default 'something'}@interface SomeAnnotation { int step()}@interface SomeAnnotation { Class appliesTo()}@interface SomeAnnotation {}@interface SomeAnnotations { SomeAnnotation[] value()}enum DayOfWeek { mon, tue, wed, thu, fri, sat, sun}@interface Scheduled { DayOfWeek dayOfWeek()}
注意:注解的成员方法是没有方法体,默认值是非必需的。
作用对象:与java注解类似,可通过Target注解来指定作用范围,如下示例:
@Target([ElementType.METHOD])@interface AppAnnotation { String value() default 'normal'}
@AppAnnotation('test')void testAnnotation() { def i = 1}
Retention注解:与java一样,不再赘述。
闭包注解:注解支持闭包作为参数,这极大的扩充了注解的应用场景。如下示例:
@Retention(RetentionPolicy.RUNTIME)@interface OnlyIf { Class value()}
class Tasks { Set result = [] void alwaysExecuted() { result << 1 } @OnlyIf({ jdk >= 6 }) void supportedOnlyInJDK6() { result << 'JDK 6' } @OnlyIf({ jdk >= 7 && windows }) void requiresJDK7AndWindows() { result << 'JDK 7 Windows' }}
class Runner { static <T> T run(Class<T> taskClass) { def tasks = taskClass.newInstance() def params = [jdk:6, windows: false] tasks.class.declaredMethods.each { m -> if (Modifier.isPublic(m.modifiers) && m.parameterTypes.length == 0) { def onlyIf = m.getAnnotation(OnlyIf) if (onlyIf) { Closure cl = onlyIf.value().newInstance(tasks,tasks) cl.delegate = params if (cl()) { m.invoke(tasks) } } else { m.invoke(tasks) } } } tasks }}
void testClosureAnnotation() { def tasks = Runner.run(Tasks) println(tasks.result)//[JDK 6, 1]或[1, JDK 6]}testClosureAnnotation()
上述run方法依据配置参数params ,通过闭包调用将task类中的requiresJDK7AndWindows过滤掉,最终只有alwaysExecuted与supportedOnlyInJDK6能执行,执行的顺序依赖于declaredMethods返回的方法数组。
Meta-annotations:作用将一个注解替代多个注解,以减少编写注解数目,如下例子:
@interface Service {}@interface Transactional {}@Service@Transactionalclass MyTransactionalService {}
使用Meta-annotations:
@Service@Transactional@AnnotationCollector@interface TransactionalService {}@TransactionalServiceclass MyTransactionalService {}
注意:Meta-annotations是groovy独有特性,在编译成字节码时会将Meta-annotations替换成Meta-annotations中声明的注解
Meta-annotations参数传递两种方式:一是在定义Meta-annotations传递,或在使用Meta-annotations时传递参数。如下例子:
@interface Service { int type()}@interface Transactional { boolean status()}@Service(type = 1)@Transactional@AnnotationCollector@interface TransactionalService {}@TransactionalService(status = true)class MyTransactionalService1 {}
- Groovy语法之类
- groovy语法
- Groovy基础语法
- Groovy的基础语法
- Groovy基本语法(1)
- Groovy基本语法(2)
- Groovy基本语法(3)
- Groovy常用语法总结
- Groovy常用语法总结
- Groovy的基础语法
- 转载Groovy基本语法
- Groovy常用语法总结
- groovy语法篇介绍
- groovy语法基础
- Groovy 简要语法
- Groovy的基础语法
- groovy语法基础
- Groovy基本语法
- android 动态改变图标颜色
- centos 中安装ffmpeg 及 libx264 库 MP3库
- java Comparator和Comparable使用
- 朴素贝叶斯-新闻分类
- Unexpected exception parsing XML document from class path resource
- Groovy语法之类
- POI各Jar包的作用
- 字符串
- android AIDL
- Android设计模式之MVVM
- 工厂模式
- 中缀表达式转后缀表达式--Java
- 只有一行VNC server running on ’::1:5900' 没有其他输出
- 成功在MP4封装的H264视频中提取能播放的裸流