Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Multi-file Programs

Let’s consider a more complex version of “Hello World!”, split across two files of source code.

  1. In the tasks/task1_2 subdirectory of your repository, create a file Hello.kt containing this code:

    fun main(args: Array<String>) {
        if (args.isNotEmpty()) {
            println(greetingFor(args[0]))
        }
        else {
            println(greetingFor("World"))
        }
    }
    
  2. Now create a new file named Greet.kt, containing the following:

    fun greetingFor(target: String): String {
        val greeting = setOf("Hello", "Hi", "G'day").random()
        return "$greeting $target!"
    }
    

    Make sure that this is in the same directory as Hello.kt. (This should be the tasks/task1_2 subdirectory of your repository.)

    Note

    These two files introduce a number of new Kotlin concepts, which we will cover in more detail later.

    Regardless, you should still be able to figure out what this code does… 😉

  3. In a terminal window, go to tasks/task1_2 and compile the program with

    kotlinc Hello.kt Greet.kt
    

    The compiler will generate a separate file of bytecode for each of the source files. If you list the directory contents, you should see HelloKt.class and GreetKt.class.

  4. Try running the program, with and without a command line argument:

    kotlin HelloKt Joe
    kotlin HelloKt
    

    Notice that there is no need to specify GreetKt here. The Java Virtual Machine (JVM) is able to find and load all of the bytecode needed to run the application. All you need to do is specify the entry point, i.e., the place where the main() function can be found.

    Remove the two .class files before proceeding further, e.g., with

    rm HelloKt.class GreetKt.class
    
  5. It’s hard to manage an application whose code is spread across multiple files of bytecode, so the Kotlin compiler allows us to bundle the code together in a single JAR file.

    Try this now:

    kotlinc -d hello.jar Hello.kt Greet.kt
    

    Check the size of this JAR file, then list its contents, using the two commands below. (Use dir instead of ls -l if you are trying this on Windows.)

    ls -l hello.jar
    jar -tf hello.jar
    
  6. Run the application in hello.jar with this command:

    kotlin -cp hello.jar HelloKt
    

    As before, you can add a command line argument to this if you wish.

    Notice the need for the -cp option here. This adjusts the JVM’s classpath so that it includes hello.jar, thus ensuring that hello.jar will be searched to find the bytecode of the application.

  7. It is also possible to bundle the Kotlin runtime library with a JAR file. Try this now:

    kotlinc -include-runtime -d hello.jar Hello.kt Greet.kt
    

    Check the size and contents of hello.jar again. You’ll see that it is now very much larger than before. Although this big increase in size is annoying for such a simple program, the advantage is that the JAR file is now portable to a system that doesn’t have Kotlin’s development tools installed. The only requirement is that a JVM be available on that system.

  8. Try running the application directly on the JVM with this command:

    java -jar hello.jar