Java Kotlin:请求迭代器()的泛型方法和for循环

Java Kotlin:请求迭代器()的泛型方法和for循环,java,generics,kotlin,Java,Generics,Kotlin,这是一个简单的通用方法,在for循环中传递args的值会导致一个错误,即: for循环范围必须具有和迭代器()方法 fun main(args:Array){ val arr:IntArray=intArrayOf(1,2,3,4) val charA:CharArray=charArrayOf('a','b','c','d')) 打印时间(arr) 印刷体(charA) } 有趣的printMe(args:T){ 用于(参数中的项目){ 打印项次(项目) } } 如何使它在char[]和ar

这是一个简单的通用方法,在for循环中传递args的值会导致一个错误,即:

for循环范围必须具有和迭代器()方法

fun main(args:Array){
val arr:IntArray=intArrayOf(1,2,3,4)
val charA:CharArray=charArrayOf('a','b','c','d'))
打印时间(arr)
印刷体(charA)
}
有趣的printMe(args:T){
用于(参数中的项目){
打印项次(项目)
}
}

如何使它在
char[]
array
的值之间进行迭代问题是编译器不知道您正在传递
数组,并且
T
可以是任何类型

解决此问题的一种方法是使用
is
运算符:

fun <T>printMe(args: T){
    if(args is Array<*>) {
            for (items in args) {
                println(items)
            }
    }
}
fun printMe(args:T){
if(args是数组){
用于(参数中的项目){
打印项次(项目)
}
}
}

这实际上有点微妙

关键问题是变量
arr
的类型为
IntArray
,而
IntArray
不是从
Array
派生的。类似地,
IntArray
有一个
iterator()
函数,但它不实现
Iterable

对于
CharArray
变量,也会发生同样的情况

事实上,
IntArray
CharArray
Array
似乎除了
any
之外没有任何公共基类或接口。因此,您要么传递对象并在
printMe
中执行类型检查,要么使用重载

类型检查版本如下所示

printMe(args:Any) {
   if(args is IntArray) {
      for(item in args) {
         println(item)
      }
   } else if (args is CharArray) {
     for(item in args) {
        println(item)
     }
   } else {
     println("Not an IntArray or a CharArray")
   }
}
重载看起来是这样的

printMe(args:IntArray) {
  for(item in args) {
    println(item)
  }
}

printMe(args:CharArray) {
  for(item in args) {
    println(item)
  }
}

IMO重载是一个更好的选择,因为你不能错误地传递一个不能处理的对象。

Kotlin中的for loop按惯例工作,静态地寻找名为
迭代器的操作符成员,它必须返回可以迭代的内容,即,依次具有操作员成员
next
hasNext
的对象

此类成员上的
运算符
修饰符需要指定该成员满足某种约定,即迭代约定

由于
args
属于
T
类型,并且在每个可能的
T
类型中都没有
iterator
成员,因此不能轻易地对其进行迭代

但是,您可以为
printMe
提供一个附加参数,该参数知道如何从
T
的实例中获取迭代器,然后使用它获取迭代器并对其进行迭代:

fun main(args: Array<String>) {
    val arr: IntArray = intArrayOf(1,2,3,4)
    val charA: CharArray = charArrayOf('a','b','c','d')

    printMe(arr, IntArray::iterator)
    printMe(charA, CharArray::iterator)

}

fun <T> printMe(args: T, iterator: T.() -> Iterator<*>) {
    for (item in args.iterator()) {
        println(item)
    }
}
fun main(args:Array){
val arr:IntArray=intArrayOf(1,2,3,4)
val charA:CharArray=charArrayOf('a','b','c','d'))
printMe(arr,IntArray::迭代器)
printMe(charA,CharArray::迭代器)
}
有趣的printMe(args:T,迭代器:T.()->迭代器){
for(args.iterator()中的项){
println(项目)
}
}
这里,
T.()->迭代器
是一种表示。可以在
T
上调用该类型的实例,就好像它们是它的扩展一样


此代码段之所以有效,是因为迭代器返回的自身有一个运算符扩展函数
iterator.iterator()=This
,它只返回该迭代器,因此允许使用for循环遍历迭代器。

这不起作用,因为IntArray和CharArray都不是数组。这是Java数组的不幸遗产。使用列表代替-它们基本上是一样的,但是使用正确的继承重载可能是最好的选择,但是我正在练习,我想知道事情是如何工作的。这很简单,但是我不喜欢将类型绑定到调用站点。感觉这太像
printMe(arr.iterator)
了,其中
printMe是由
fun printMe(iterator:iterator)``给出的。@MichaelAnderson您也可以将printMe称为
printMe(arr,{iterator()})
。我同意在这种情况下,您只需传递迭代器本身,但有时您可能需要在
printMe
中多次实例化它,或者使用
args
执行其他操作。
fun main(args: Array<String>) {
    val arr: IntArray = intArrayOf(1,2,3,4)
    val charA: CharArray = charArrayOf('a','b','c','d')

    printMe(arr, IntArray::iterator)
    printMe(charA, CharArray::iterator)

}

fun <T> printMe(args: T, iterator: T.() -> Iterator<*>) {
    for (item in args.iterator()) {
        println(item)
    }
}