大佬教程收集整理的这篇文章主要介绍了groovy – 有没有办法让@Builder注释适用于不可变类?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经开始更深入地研究AST转换注释的使用 – 它们帮助显着减少了我在某些地方编写的代码量.但是,我在使用groovy.transform.builder.builder注释和我的一个不可变值类时遇到了问题.此批注的来源是here.
问题是注释似乎使构建器直接设置了构建器的值,而不是存储值的副本并将它们传递给构建器的构造函数.当您尝试将其与不可变类一起使用时,这会导致ReadOnlyPropertyException.
您可以使用此注释选择四种可能的构建器策略,其中我尝试过DefaultStrategy,ExternalStrategy和InitializerStrategy.但是,所有这些都造成了问题.
ExternalStrategy看起来像四个中最有希望的,你可以找到一个基于它的SSCCE详细说明问题
编辑
我尝试使用下面的CFrick答案,使用InitializerStrategy而不是ExternalStrategy.
现在一切都在编译,但是当我尝试执行测试时,我在运行时遇到以下错误:
java.lang.IllegalAccessError: tried to access class com.github.tagc.semver.version.baseVersion from class com.github.tagc.semver.version.baseVersion$com.github.tagc.semver.version.baseVersionInitializer at java.lang.Class.getDeclaringClass(Class.java:1227) at java.beans.MethodRef.set(MethodRef.java:46) at java.beans.MethodDescriptor.setMethod(MethodDescriptor.java:117) at java.beans.MethodDescriptor.<init>(MethodDescriptor.java:72) at java.beans.MethodDescriptor.<init>(MethodDescriptor.java:56) at java.beans.Introspector.getTargetmethodInfo(Introspector.java:1163) at java.beans.Introspector.getBeanInfo(Introspector.java:426) at java.beans.Introspector.getBeanInfo(Introspector.java:173) at com.github.tagc.semver.version.VersionFactory.createBaseVersion(VersionFactory.groovy:34) at com.github.tagc.semver.test.util.TestSetup.<clinit>(TestSetup.groovy:77) at java.lang.Class.forName(Class.java:344) at com.github.tagc.semver.version.SnapshotDecoratorSpec.#decoratedVersion should be considered equal to patch-bumped #releaseVersion snapshot(SnapshotDecoratorSpec.groovy:24)
之后是一系列例外情况,如下所示:
java.lang.NoClassDefFoundError: Could not initialize class com.github.tagc.semver.test.util.TestSetup at java.lang.Class.forName(Class.java:344) at com.github.tagc.semver.version.SnapshotDecoratorSpec.#decoratedVersion should be considered equal to minor-bumped #releaseVersion snapshot(SnapshotDecoratorSpec.groovy:36)
我现在拥有的BaseVersion类如下:
/** * A concrete,base implementation of {@link com.github.tagc.semver.version.Version Version}. * * @author davidfallah * @since v0.1.0 */ @Immutable @Builder(prefix = 'set',builderStrategy = InitializerStrategy) @PackageScope final class BaseVersion implements Version { // ... /** * The major category of this version. */ int major = 0 /** * The minor category of this version. */ int minor = 0 /** * The patch category of this version. */ int patch = 0 /** * Whether this version is a release or snapshot version. */ Boolean release = false // ... }
生产这些实例的工厂:
/** * A factory for producing base and decorated {@code Version} objects. * * @author davidfallah * @since v0.5.0 */ class VersionFactory { // ... /** * Returns an instance of {@link com.github.tagc.semver.version.baseVersion BaseVersion} constructed * with the given parameters. * * @param major the major category value of the version instance * @param minor the minor category value of the version instance * @param patch the patch category value of the version instance * @param release the release setTing of the version instance * @return an instance of {@code BaseVersion} */ static BaseVersion createBaseVersion(int major,releasE) } /** * Returns an instance of {@link com.github.tagc.semver.version.baseVersion BaseVersion} constructed * with the given parameters. * * @param m a map of parameter names and their corresponding values corresponding to the * construction parameters of {@code BaseVersion}. * * @return an instance of {@code BaseVersion} */ static BaseVersion createBaseVersion(Map m) { return new BaseVersion(m) } /** * Returns an instance of {@link com.github.tagc.semver.version.baseVersion BaseVersion} constructed * with the given parameters. * * @param l a list of parameter values corresponding to the construction parameters of {@code BaseVersion}. * * @return an instance of {@code BaseVersion} */ static BaseVersion createBaseVersion(List l) { return new BaseVersion(l) } /** * Returns a builder for {@link com.github.tagc.semver.version.baseVersion BaseVersion} to specify * the construction parameters for the {@code BaseVersion} incrementally. * * @return an instance of {@code BaseVersion.builder} */ static Object createBaseVersionBuilder() { return BaseVersion.builder() } // ... }
Version对象的测试规范类:
/** * Test specification for {@link com.github.tagc.semver.version.Version Version}. * * @author davidfallah * @since 0.1.0 */ @Unroll class VersionSpec extends Specification { static exampLeversions = [ VersionFactory.createBaseVersion(major:1,minor:2,patch:3),VersionFactory.createBaseVersion(major:0,minor:0,patch:0),VersionFactory.createBaseVersion(major:5,minor:4,VersionFactory.createBaseVersion(major:1,minor:16,patch:2),VersionFactory.createBaseVersion(major:4,minor:5,patch:8),] // ... }
尝试创建失败的BaseVersion实例的其他类,例如TestSetup.
def v = new Value().with{ SETVALue(1); return it }
这不能在@Immutable对象上完成.
根据docs,只有InitializerStrategy,它可以明确地处理@Immutable.
例如.
import groovy.transform.* import groovy.transform.builder.* @Immutable @ToString @Builder(prefix='set',builderStrategy=InitializerStrategy) class Value { int value } def builder = Value.createInitializer().SETVALue(1) assert new Value(builder).toString()=='Value(1)'
根据你的目标,这是一个更糟糕的语法,你可能最好只使用基于地图的c’tors.即使没有例如@Typechecked一个新值(vlaue:666)将生成一个错误,并且让params(对于具有多个属性的类)将使它们保持为空.
以上是大佬教程为你收集整理的groovy – 有没有办法让@Builder注释适用于不可变类?全部内容,希望文章能够帮你解决groovy – 有没有办法让@Builder注释适用于不可变类?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。