加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

泛型 – 泛型类型的闭包参数 – 异常

发布时间:2020-12-14 16:31:59 所属栏目:大数据 来源:网络整理
导读:在下面的代码中,为什么Groovy似乎忽略了方法barMany中提供的closure参数的泛型类型声明: import groovy.transform.CompileStatic@CompileStaticclass Main { static main(args) { FooSub foo = new FooSub() BarSub bar = new BarSub() }}@CompileStaticcla
在下面的代码中,为什么Groovy似乎忽略了方法barMany中提供的closure参数的泛型类型声明:

import groovy.transform.CompileStatic

@CompileStatic
class Main {
    static main(args) {
        FooSub foo = new FooSub()
        BarSub bar = new BarSub()
    }
}

@CompileStatic
class Foo<T> {
    void fooOne (T item) {}
    void fooMany(List<T> items) {
        items.each { T item -> fooOne(item) } // Compiles fine.
    }
}

@CompileStatic
class FooSub extends Foo<Integer> {}

@CompileStatic
class Bar<T extends Bar<T>>  {    
    void barOne (T item) {}
    void barMany(List<T> items) {

        items.each { T item -> barOne(item) } // Error:
        // Cannot find matching method Bar#barOne(java.lang.Object) !!!

        items.each { T item -> barOne(item as T) } // Error:
        // Expected parameter of type java.lang.Object but got T  !!!

        items.each { item -> barOne(item as T) } // Compiles fine - closure knows about T

    }
    void barManyMore(List<T> items) {
        for (T item in items) { // Compiles fine.
            barOne(item) }
    }
}

@CompileStatic
class BarSub extends Bar<BarSub> {}

更新:
Groovy版本:2.4.5 JVM:1.7.0_80供应商:Oracle Corporation操作系统:Linux

更新
所以我之前没有注意到这个奇怪的错误 – org.codehaus.groovy.control.MultipleCompilationErrorsException:启动失败 – 我将发布完整输出:

~/grov/tests$groovyc generics.groovy 
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
generics.groovy: 27: Expected parameter of type java.lang.Object but got T
 @ line 27,column 19.
        items.each { T item -> barOne(item) } // Error:
                     ^

generics.groovy: 27: [Static type checking] - Cannot find matching method Bar#barOne(java.lang.Object). Please check if the declared type is right and if the method exists.
 @ line 27,column 29.
        items.each { T item -> barOne(item) } // Error:
                               ^

generics.groovy: 30: Expected parameter of type java.lang.Object but got T
 @ line 30,column 22.
           items.each { T item -> barOne(item as T) } // Error:
                        ^

3 errors

~/grov/tests$groovyc -v
Groovy compiler version 2.4.5
Copyright 2003-2015 The Apache Software Foundation. http://groovy-lang.org/

更新

完整性的一些更多变通方法:
这些变通办法似乎有效:

Closure c = { T item -> barOne(item) }; items.each c // See comments by @tim_yates
    items.each ( { T item -> barOne(item) } as Closure)  // Casting to closure works too!

当类型是基于泛型T的类时,同样的问题也适用:

@CompileStatic
class Baz<T extends Baz<T>>  {
    List<T> getList() {
        return [new T(),new T()]
    }
}

@CompileStatic
class BazClient {
    void useBaz(Baz baz) {
        // baz.getList().each {Baz it -> println it} // Error
        Closure c = {Baz it -> println it}; baz.getList().each c  // works
        baz.getList().each ({Baz it -> println it} as Closure) // works
    }
}

解决方法

这是与泛型相关的 bugs之一,已在Groovy 2.4.6中修复.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读