Eclipse里生成Guava-based的hashCode()和equals()

做Java开发的常常要重写类的hashCode()和equals()。一般情况下,可以套常用的模板。Eclipse就套用这些模板,直接生成默认实现,可实现比较冗长,比如下面的例子

有类A,

Eclipse的默认实现是这样的,

显然实现比较冗长,也比较乱,包含了很多细节,有些也不符合代码规范(比如if后没有花括号)。

用过Guava的同学都知道,使用Objects类可以大大简化这两个函数的实现。我试着扩展了Eclipse JDT,套用Guava的实现模板,那代码就漂亮多了。Guava隐藏了大量的实现细节。

如下,

具体的代码实现在Github上,点这

主要分如下有几步,

  • Project Explorer的上下文菜单中加入新的功能选项。
  • 通过Eclipse里事件得到Java CompliationUnit,使用ASTParser得到类里的Non-Static Member Field,然后就套用新模板吧。
  • 一个源文件中可能包含多个Java Class,所以还要有个Dialog来选择在哪个类中实现方法 。

其他细节都在代码里的,有兴趣的就看看吧。😁

聊聊ClassLoader in Java World

ClassLoader是Java技术中非常主要的概念,原因是它用来加载Java Class。如果没有Class,也就没有对象;没有对象,就没有之后的一切了。

Java ClassLoader的默认实现是一种双亲结构,即总是尝试让Parent ClassLoader加载类。这样有一些优点,当然也有很大的限制,比如就不利于不同Module对多版本类的加载。更多的细节,在下面我做的PPT里。

还有些新的理解和发现。

  • 自定义的ClassLoader可以把Parent ClassLoader设置为null,如果再把loadClass函数重写,就可以完全屏蔽default classLoader的影响。如OSGi的Bundle ClassLoader的最终的Parent就不是Bootstrap ClassLoader(Bundle ClassLoader的实现还是会去从默认ClassLoader去加载java.*的类)。
  • 程序执行时,ClassLoader的选择。做几个小实验你就会发现,默认的ClassLoader是“加载当前执行函数所在类的ClassLoader”。在OpenJDK的源码中一通Search,就可以找到一些端倪。

在源文件src\interp\engine\interp.c中,有executeJava()函数中,执行ByteCode之前,先准备了MethodBlock的指针,它中间

可以看看GETSTATIC这个指令的实现(此指令会在读取类的静态方法时调用)。可以看到resolveField()方法,并在mb的Class指针传入。idx是Static Field对应Constant Pool里的index。

resolveField中被调用resolveClass函数

resolveClass又回调用findClassFromClass(其实是个Macro),同样传入class指针。看看Macro的定义,就可以很清楚了。

是从ClassBlock结构中找到对应的ClassLoader.

其实记住这个结论就好。这样就可以完全打错传统的ClassLoader的限制,比如OSGi Plugin/Bundle里的所有类就是由OSGi自己的加载器加载的,非常灵活,可以实现非常牛逼的功能!