How do I do this ... for (file in fileList) {...}?


#1

I have the following line of code:

  val fileList = dir.listFiles()

Which returns an array of java.io.File objects (File[] is the return type).

I am trying to do something like this:

for (file in fileList) {
  // do something with each file
  }

But I keep getting a message For-loop range must have an iterator() method.

I’ve tried

for (i in fileList.indices) {
//
  }

and I get the same message.

What is the proper construct for this loop?

Thank you!

Randy


#2

The error you are getting is (admittedly) not direct enough, but it's telling you that theres no iterator() method on the type "Array<File>?", which means that listFiles() may return null, over which it's hard to iterate. The best solution is to handle the null case properly, for example

if (fileList == null) throw IllegalStateException("...")

for (filr in fileList) {…}


If for some reason you are sure that fileList will not be null, you can say

for (file in fileList!!) {...}

And get an exception if fileList happens to be null


#3

Nicely done! Love the flow analysis.

The error message did lead me to understand that there was no iterator() available. What I didn’t understand was the root cause being a potential null value. I’m glad you are thinking about error messages as that will be an important part of the journey for developers moving to Kotlin. Maybe “For-loop requires an iterator() which is not available on nullable value”? Or something like that.

Thank you.

Randy


#4

Have you considered the alternative option of :

for (file in fileList?) {...}

It seems like that would be an elegant way to solve this sort of issue, especially with java interop.


#5

Yes, we did: we call it "fileList!!" (See above)


#6

Yes, I tried that but it does not compile. The alternate:

for (file in fileList!!) {
}

does work.

I am going to use the approach of testing for null and doing something else (such as throw an exception), so that I have choice on action - log something, throw exception, pick a default, etc.


#7

But, if fileList is null, you get an Exception at runtime, right?  With the ?, I would have assumed it would just skip evaluation and hence the loop, rather than blow up.


#8

John,

It’s my understanding that using fileList!! would mean that it would NPE if it’s null. I looked at the Java code and it can return a null. (I don’t know why or what that signifies, but that’s my reading of the code).

In this particular case, I am electing to do a null value check (==null) and then take an appropriate action. There are cases when you are certain that you won’t get a null that the !! option makes sense.

I am using Kotlin with NetKernel and I am going to review the internal code of NetKernel to figure out when and where null values could be returned and when they could not and start to either request a source code change to mark them with annotations or build an annotation file. (I have to research both of these approaches to see which I want to use).

– Randy


#9

Often times it's much better to blow up )