I have the following property declaration in a com...
# getting-started
e
I have the following property declaration in a companion object:
Copy code
class WordleGame(val secretWord: String) {
    companion object {
        private val words = java.io.File("words.txt").readLines()

        fun playGame() {
            val game = WordleGame(words.random())
            ...
        }
    }
}

fun main() {
    WordleGame.playGame() // ExceptionInInitializerError
}
Is there a clean way to catch a
FileNotFoundException
? I can catch a
ExceptionInInitializerError
in
main()
and pull out its cause, but I'm hoping for something easier to explain to students, possibly restructuring the code.
c
load the file in the playGame() factory method.
e
Thanks, but I want to load the file only once, not each time
playGame()
is called.
c
any particular reason for that? performance-wise it would be negligible to read a text file, and it fits in with the flow of “preparing everything to play a game”.
e
if you use
lazy
then it will be loaded in the stackframe of the usage and an error will be thrown without being wrapped
but how about reading from a resource instead. no FileNotFoundException if you've set up your build correctly
e
I'm trying to teach them about how to handle exceptions so want to purposely generate one.
performance-wise it would be negligible to read a text file
In my other thread, I'm being told that concatenating a string message is so expensive it should be done lazily. 😅 https://kotlinlang.slack.com/archives/C0B8MA7FA/p1667832150499759
c
it’s all relative. In the context of a one-time-load-a-file-to-play-a-game, the performance impact is negligible. In the context of validating method parameters, which can be done multiple times, the idiomatic approach is already to lazy evaluate there as the “failure” path is relatively expensive to calculate and generally not executed (relative to the boolean check).
you can, of course, cache the loading of the file -
lazy
will work for that - but that’s getting into complexities beyond what it appears you are teaching.
👍 1
e
Thanks. Sounds like I should use other examples of exceptions, such as the user entering a word of the wrong length.
t
You can also load it in main and pass it as an argument to playGame() (that's how I would program it myself in the real world as well)
y
I'm surprised this hasn't been mentioned. You can just do this:
Copy code
companion object {
    private val words = try {
        java.io.File("words.txt").readLines()
    } catch (e: FileNotFoundException) {
        // Provide default value
        listOf("foo", "bar", "baz")
    }
g
A few points from commercial/real life development practices about those examples. We would separate word reading and playing the game. All caching would be done on level of some higher level code rather adding it into factory of WordleGame, same as Ties suggested Also reading file on class initialisation wouldn’t be allowed, because it slowdowns app init, we would do it explicitly and probably asynchronously with coroutines and passed result into WordleGame after