Groovy 中当调用对象引用上的一个方法时,我们一般是obj.methodName()
,这种方式就和 java 一样限制了方法名的格式不能包含特殊字符(譬如-``.
等),但是 Groovy 对其有了另一种强大的支持,即obj.’my.method-Name’()
是可以调用成功的,这就使得实例的方法调用可以变成动态的,譬如obj."${var}"()
,我们对 var 变量进行动态修改即可。
Groovy 提供了?.
操作符来进行安全的引用,当操作符之前是一个 null 引用的时候,则表达式被终止且返回 null,这和 Kotlin 的?.
是一个道理。
构造方法
Groovy 对 java 的构造方法进行了拓展,具体表现如下。
位置参数:构造方法默认是 public 的,我们可以通过三种途径调用构造方法,即常用的 java 方式,使用 as 关键字进行强制造型和使用隐式造型。
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
class MetaCreater {
String name, address;
//位置参数构造方法定义
MetaCreater(name, address) {
this.name = name;
this.address = address;
}
}
//当 groovy 看到需要将一个列表造型成别的类型的时候,
//它试图使用列表的所有元素按照顺序位置作为参数来调用该类型的构造方法,
//这在使用 as 关键字进行造型或者通过赋值来进行静态类型引用的时候是很有用的。
def a = new MetaCreater(‘aa’, ‘a-a’);
def b = [‘b’, ‘b-b’] as MetaCreater;
MetaCreater c = [‘c’, ‘c-c’]
命名参数:上面使用位置参数太多的时候就不灵活了,因为我们必须考虑到构造方法需要的可选参数场景,而命名参数就能很好的解决这个问题。
class MetaCreater {
String name, address;
}
//隐式的命名构造方法不再有效
new MetaCreater()
//命名参数
new MetaCreater(name: ‘a’);
new MetaCreater(name: ‘a’, address: ‘a-a’);
new MetaCreater(address: ‘a-a’);
隐式构造方法:通过简单的提供构造方法的参数列表来隐式的调用构造方法。隐式构造方法经常用来作为 builder。
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
class MetaCreater {
String name, address;
//位置参数构造方法定义
MetaCreater(name, address) {
this.name = name;
this.address = address;
}
}
//隐式构造
MetaCreater c = [‘c’, ‘c-c’]
Groovy 类在字节码级别就是 Java 类,所以 Groovy 对象在内存中就是 Java 对象,在源代码级别 Groovy 类和对象处理几乎是 Java 语法的一个超集,只有嵌套类是一个例外,当前 Groovy 语法还不支持嵌套类,并且在数组的定义上有微小的改变。
文件和类的关系
-
如果一个 groovy 文件不包括类声明,那么它被作为一个脚本处理。即包装成继承 Script 类实现,自动生成的类的名称与源文件名称相同,文件内容被包装进一个 run 方法中,并且增加了一个 main 方法用来启动脚本。
-
如果 groovy 文件中只包含一个类声明,并且这个类的名称与文件名相同,则含义与 java 中一样。
-
如果一个 groovy 文件包含多个不同访问范围的类(类名没必要和文件名一样)声明,groovyc 编译器完美的为所有在这个文件中声明的类创建
*.class
文件,如果你希望直接调用你的脚本,例如在命令行或者 IDE 中使用 groovy, 那么在你的文件中的第一个类中应该有一个 main 方法。 -
如果一个 groovy 文件混合了类的声明和脚本代码,在这种情况下,脚本代码将变成一个主类被执行,因此不要声明一个与源文件同名的类。
-
当没有进行显式编译的时候,groovy 通过匹配相应名称的
*.groovy
源文件来查找类,在这点上,名称变得十分重要,groovy 仅仅根据类名称是否匹配源文件名称来查找类,当这样的一个文件被找到的时候,在这个文件中声明的所有类都将被转换,并且 groovy 在后面的时间都将能找到这些类。
在包中组织类
Groovy 延续了 Java 包结构组织文件的方式,包结构用来在文件系统中找到相应的类文件。由于*.groovy
源文件不需要编译成*.class
文件,因此在查找类的时候也需要查找*.groovy
文件,Groovy 查找*.groovy
时重用了类路径。当我们查找一个给定的类的时候,如果 groovy 同时找到了一个*.class
和*.groovy
文件,它使用最后修改的那个文件,也就是说,如果源文件在上一次编译之后做了修改,groovy 将重新编译源文件到*.class
文件。
Groovy 跟随 Java 的导入语句,在声明类之前进行导入。默认情况下 groovy 导入了 6 个包和两个类,这使得每个 groovy 源代码程序看起来都包含了下面的初始化语句:
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
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
在 Groovy 中的 import 语句有另外一个强大的作用,它可以与 as 关键字一起使用,这可以用来作为类型的别名,而一般的 import 语句运行使用类的名称来应用来,通过类型别名你可以使用任何你喜欢的名称来引用一个类,这个特性解决了类名称冲突的问题并且支持本地修改一个第三方类库的特性。
//------------ 支持本地修改一个第三方类库的特性案例 ------------
package thirdparty
class MathLib {
Integer twice(Integer value) {
return value * 3 // intentionally wrong!
}
Integer half(Integer value) {
return value / 2
}
}
assert 10 == new MathLib().twice(5) //false
assert 2 == new MathLib().half(4) //true
//我们可以使用类型别名来重命名原始的类,然后使用继承来修复它,不用修改原来已经使用的代码。
import thirdparty.MathLib as OriginalMathLib
class MathLib extends OriginalMathLib {
Integer twice(Integer value) {
return value * 2 // fix third bug
}
}
assert 10 == new MathLib().twice(5) //true
assert 2 == new MathLib().half(4) //true
//----------------- 类名称冲突的问题案例 ------------------
//假设我们需要使用下面的额外的数学库
package thirdparty2
class MathLib {
Integer increment(Integer value) {
return value + 1
}
}
//上面的类虽然它在不同的包中,但是有一个与前面的类型相同的名称,
//如果不使用别名,那么我们在代码中必须有一个类使用全限定名称或者两个都使用全限定名称,
//通过别名,我们可以通过一种优雅的方式来避免这种情况。
import thirdparty.MathLib as T1MathLib
import thirdparty2.MathLib as T2MathLib
assert 3 == new T1MathLib().half(new T2MathLib().increment(5)) //true
Groovy 除过具备 Java OO 的特性外,自己还有一些额外的特性。
Multimethods
Groovy 的方法查找是方法参数的动态类型化,而 java 是静态类型的,这个 groovy 的特性叫做复合方法 Multimethods。
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
def func(Object obj) {
return ‘object’
}
def func(String str) {
return ‘string’
}
Object x = 1
Object y = ‘foo’
assert ‘object’ == func(x)
assert ‘string’ == func(y) // groovy 中 true,java 中 func(y) 返回 object
参数 x 是 Object 静态类型和 Integer 动态类型,参数 y 是 Object 静态类型和 String 动态类型。两个参数有相同的静态类型,两次都采用与 java 等价的方式传递给 func(Object),由于 groovy 通过动态类型进行方法分派,所以 func(String) 的专门实现被用在第二中情况。
可以看到,调用 func 方法的地方可能完全不知道其差异,从一个调用者的角度看,它就像 func(String) 覆盖了 func(Object),这在 java 中是办不到的。所以在 groovy 中通过这种能力,能使我们通过适当的覆盖行为更好的避免重复的代码。
GroovyBean 特性
Groovy 通过特定的语言支持使得 JavaBean 的使用更加简单,这种使用包含了三个方面:
-
创建 JavaBean 类特殊的 Groovy 语法;
-
不管 JavaBean 是在 groovy 中还是在 java 中声明的,groovy 提供了容易访问 Bean 的机制;
-
对 JavaBean 的事件处理提供支持;
一般我们都是通过.
进行属性访问,但是也有一些特例,我们还可以通过.@
进行属性访问,譬如:
class Bean {
public value
void setValue(value) {
this.value = value
}
void getValue() {
value * 2
}
}
def bean = new Bean(value: 100)
assert 200 == bean.value
assert 100 == bean.@value
上面例子其实就是 Groovy 的一个特例规则,**在类内部,引用fieldName
或者this.fieldName
将被解释为直接属性访问,而不是 bean 风格的属性访问(通过访问方法进行);在类的外部,可以使用reference.@fieldName
语法直接访问类属性,而不是 bean 风格的属性访问(通过访问方法进行)。
Groovy 不识别 bean 和其他类型的对象的区别,它仅仅依赖相应的 getter 和 setter 方法是否可用。我们可以通过一个实例对象的 getProperties 方法和 properties 属性来获取到实例对象属性的 map (key 为属性名称,value 为属性值)列表,操作样例如下:
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
class SomeClass {
def someProperty
public someField
private somePrivateField
总结
首先是感觉自己的基础还是不够吧,大厂好像都喜欢问这些底层原理。
另外一部分原因在于资料也还没有看完,一面时凭借那份资料考前突击恶补个几天居然也能轻松应对(在这里还是要感谢那份资料,真的牛),于是自我感觉良好,资料就没有怎么深究下去了。
之前的准备只涉及了Java、Android、计网、数据结构与算法这些方面,面对面试官对其他基础课程的考察显得捉襟见肘。
下一步还是要查漏补缺,进行针对性复习。
最后的最后,那套资料这次一定要全部看完,是真的太全面了,各个知识点都涵盖了,几乎我面试遇到的所有问题的知识点这里面都有!希望大家不要犯和我一样的错误呀!!!一定要看完!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
,那套资料这次一定要全部看完,是真的太全面了,各个知识点都涵盖了,几乎我面试遇到的所有问题的知识点这里面都有!希望大家不要犯和我一样的错误呀!!!一定要看完!**
[外链图片转存中…(img-drTu1YNh-1714499973079)]
[外链图片转存中…(img-nqDVH2Vv-1714499973079)]
[外链图片转存中…(img-rUDSg7KQ-1714499973079)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!