使用Groovy的构造函数Coersion时出现java.lang.UnsupportedOperationException

时间:2017-04-28 17:32:47

标签: groovy

为什么我不能将我的地图强制转换为IStringHolder的构造函数?

当我运行Example.main

$('#btnSubmit').on('click', function() {
  alert('test');
  var propertyAdd = $('#additions_info_0_0').val();
  var mobile = $('#additions_info_0_1').val();

  var StringContent = '<p>I am thrilled to share my new listing with you at ' + propertyAdd + '. To find out more about this exciting property, or to hear about one of the many others currently on the market, call me to set up an appointment at ' + mobile + ' I would be happy to answer your questions, discuss your needs, and set you on track to achieving your real estate goals. Looking forward to hearing from you soon!</p>';

  $('#contentDiv').html(StringContent);
});

我收到以下异常

interface IStringHolder {
    String getString()
}

class StringHolder implements IStringHolder {
    String string

    StringHolder(string) {
        this.string = string
    }

    @Override
    String getString() {
        return string
    }
}

class Example {
    public static void main(String[] args) {
        doSomething([string:"hey"] as IStringHolder)

    }

    static void doSomething(IStringHolder stringHolder) {
        println stringHolder.getString()
    }

}

为什么例外来自Example.doSomething的第一行?

当我将地图强制转换为StringHolder时,它会起作用。发生了什么事?

1 个答案:

答案 0 :(得分:2)

问题

此代码存在以下问题:

doSomething([string:"hey"] as IStringHolder)

您尝试利用Groovy的语言功能称为显式构造函数强制,它在IStringHolder类中查找可以使用您提供的参数调用的构造函数

在这种情况下,Groovy将在IStringHolder类中查找它可以调用以实例化它的无参数构造函数,然后它将查找一个setter setString(String str)并使用{{ 1}}你提供了。

您看到"hey"的原因是因为UnsupportedOperationException中没有构造函数可以调用,因为它不是实现。

将类型强制转换为IStringHolder确实有效,但可能并不像您期望的那样。如果你只提供了as StringHolder,而不是"hey",它就会完成你所期望的和我上面详述的内容。这是因为映射被解释为Named Argument Constructor,这会导致Groovy使用它可以找到的唯一构造函数来实例化对象,将string:"hey"传递给它,然后调用合成的null方法一旦它被构建,就setString(String str)。虽然这会产生您正在寻找的结果,但它会以非直观的方式实现。

解决方案

显式构造函数强制

"hey"

在这里,Groovy将寻找一个构造函数,该构造函数采用类型StringHolder stringHolderImpl = [ "hey" ] as StringHolder 的一个arg并将值String传递给它。


隐式构造函数强制

"hey"

这与上面相同,除了Groovy使用左侧类型来确定右侧可能是什么,在继续查找构造函数之前等等。

我不建议这只是因为它让Groovy假设太多,而像Intellij这样的IDE会抱怨这种语法。


明确关闭强制

如果您坚持不使用实现类StringHolder stringHolder = [ "hey" ] ,可以通过以下方式在运行时创建实现:

StringHolder

这会创建一个满足IStringHolder stringHolderImpl = { getString: "hey" } as IStringHolder 契约的闭包,因此可以很容易地将其转换为它的实现。


隐含关闭强制

IStringHolder

我再也不推荐这种风格,但它有效。


我的想法

由于显式特性,我是显式构造函数强制的粉丝,因为它不需要创建闭包的开销。当我需要一个只需要在运行时存在的类的实现时,我将不时使用显式闭包强制。

什么是最好的选择?你必须自己确定一下!


TL;博士