Size, complexity, and quality of code#
While using Java, developers typically have to write more lines of code, while Kotlin enables developers to accomplish the same tasks without writing so much code, making it more expressive.
Further, it helps developers to make code more organized, readable and reusable. So, some developers opt for Kotlin to develop a concise, readable and maintainable code base.
To help manage the quality of your code, Kotlin makes use of type inferencing, eliminating much of the frustrating and overly tedious syntax that Java developers face. Often, code written in Kotlin is more concise, but it also happens to be a little more complex for those used to programming in Java.
Null Safe#
In Java, NullPointerException causes a lot of frustration for developers, they can even be the main reason why you would experience crashes in your app.
However, in Kotlin, all types of variables are non-nullable by default. So if you try to assign or return null values, Kotlin will catch NPEs at compile time.
Coroutines support#
In Java, whenever you start a long running process with CPU intensive operations, the corresponding thread will be blocked. You can create multiple threads in the background, but managing them is a complex task.
In Kotlin you can create multiple threads to run long processes, and with coroutine support, it will suspend execution at a certain point without blocking threads.
Type inference#
In Java you need to specify a type of each variable when you declare it. In Kotlin, you don’t need to specify the type of each variable.
Functional programming#
Java has support for functional programming but it’s only available in Java 8, whereas most Android development is done with Java 6 and 7.
Kotlin is a mix of functional and procedural programming which consists of many useful methods such as lambdas, higher-order functions, lazy evaluation, etc. Most of these methods are not offered for Android developers in Java 8.
Introduction to Kotlin language and syntax#
Kotlin aims to be a readable, pragmatic, safe, and interoperable programming language:
-
Readability is supported by language features such as type inference, data classes, and infix functions. Such features allow writing concise code without losing readability.
-
Pragmatism is crucial because Kotlin is for large-scale enterprise software development. JetBrains use it themselves to develop their IDEs. Thus, Kotlin incorporates industry feedback and addresses issues of large-scale software development.
-
Safety aims to prevent common software bugs by design. This is aided by several language features such as nullable types (to prevent null pointer exceptions) and by nudging you towards best practices such as designing for inheritance.
-
Interoperability with Java is a major selling point of Kotlin and a necessary base for its widespread adoption in the JVM world. Interoperability allows Kotlin and Java to be used side by side, including the use of Java libraries or frameworks from Kotlin.
For instance, the Kotlin standard library interoperates with Java by reusing the Java Collections API. Similarly, it interoperates with JavaScript in the context of Kotlin/JS.
Now that you have a basic understanding of the philosophy of the language, let’s dive in and understand how to use this language.
Read-only vs Mutable variables#
Let’s start with the Kotlin basics: declaring variables. Kotlin fundamentally differentiates between read-only and mutable data.
Mutable variables#
To declare a mutable variable, you use the var
keyword:
var number = 17
println("number = $number")
number = 42 // var can be reassigned
println("number = $number")
Mutable means that the variable can be reassigned to a different value after initial assignment.
Read-only variables#
In contrast, a read-only variable can be declared using val
(instead of var
):
val number = 17
println("number = $number")
number = 42 // Not allowed, throws an exception
Read-only means that the variable cannot be reassigned once initialized.
You should prefer read-only variables to mutable ones whenever possible, i.e., whenever you don’t have to change the value after initialization.
Tip: Prefer val
to var
to simplify data flow and facilitate reasoning about your code.
Summary#
Kotlin differentiates between read-only and mutable variables at declaration time, forcing you to think about the mutability of state from the start.
val
lets you declare read-only variables.
var
lets you declare mutable variables.
- Good practice is to prefer
val
over var
whenever possible to reduce mutability and therefore facilitate understanding of the program’s state and data flow.
Keep learning about Kotlin.#
Get to developing your own apps fast.
Educative’s text-based courses feature hands-on practice to get you get you up-to-speed quickly.
Kotlin Crash Course for Programmers
Basic data types#
Here, we’ll take a look at integers, floating point numbers, text, and booleans.
Integers#
There are four basic data types to store integer numbers of different sizes in Kotlin:
val byte: Byte = 127
val short: Short = 32767
val int: Int = 2147483647
val long: Long = 9223372036854775807
Floating Point Numbers#
Additionally, Kotlin has Float
and Double
to store floating point numbers up to different precision and sizes:
val float: Float = 3.4028235e38f
val double: Double = 1.7976931348623157e308
Two things to note:
- The
e
in both values denotes exponentiation, for instance 10e3 == 1000
.
- In order to denote a
Float
value, you have to add the f
suffix. Otherwise, Kotlin infers Double
as the type of the number.
Text#
Kotlin uses the Char
type for single characters and String
for arbitrary sequences of characters:
val character: Char = '#'
val text: String = "Learning about Kotlin's data types"
Single characters are denoted using single quotes ''
, whereas basic strings use double quotes ""
.
However, you can also use multiline strings by wrapping your string into three double quotes: """<multiline string here>"""
.
Booleans#
Finally, Kotlin uses Boolean
to store either true
or false
:
val yes: Boolean = true
val no: Boolean = false
Summary#
Here’s what you should take away from this section:
- Kotlin has
Byte
, Short
, Int
, and Long
as basic types for integer numbers.
- Kotlin uses
Float
and Double
for floating point numbers. A Float
is denoted with a trailing f
, as in 17f
.
- Kotlin has
Char
to store single characters and String
to store strings of text.
- Kotlin’s basic types map to Java’s primitive types when targeting the JVM (and
String
maps to String
).
Kotlin’s type inference#
Type inference is a compiler feature that allows you to omit types in your code when the compiler can infer it for you.
Type Inference in Kotlin#
Kotlin’s compiler can infer the types of most variables, so adding the type is optional:
// Run the code to see the variable's types
val string = "Educative"
val int = 27
val long = 42L
val double = 2.71828
val float = 1.23f
val bool = true
Type Inference for Literals#
The compiler automatically infers that the string variable must have type String
because it’s assigned to the value "Educative"
.
For integer values, the compiler infers Int
by default. You can use the L
suffix as in 42L
to transform the value into a Long
. Similarly, the compiler infers Double
for floating point numbers unless you add an f
as suffix as in 1.23f
, in which case it is considered a Float
. There’s no such shortcut suffix for Byte
or Short
because these aren’t used as often.
Type Inference for Objects#
Naturally, type inference doesn’t only work with literal values on the right-hand side. The compiler can infer types of object just as easily:
import java.util.*
import java.time.*
import java.io.*
val stringBuffer = StringBuffer("PREFIX")
val localDate = LocalDate.now()
val file = File("foo.txt")
Summary#
Here are the key takeaways:
- The Kotlin compiler can infer most types.
- Writing down the type explicitly is optional in these cases.
- You may prefer to use explicit types for clarity.
- Especially when the right-hand side is a complex expression or function call.
- Inferred types are ubiquitous in idiomatic Kotlin code.
Conditions with “if”#
Conditions with if
can be written as follows:
if (planet == "Jupiter") {
println("Radius of Jupiter is 69,911km")
} else if (planet == "Saturn") {
println("Radius of Saturn is 58,232km")
} else {
println("No data for planet $planet")
}
Each condition is followed by a block of code in curly braces. There can be any number of else-if blocks (including zero) and up to one else-block.
Note: In the else-block, the planet variable is included in the output string using string interpolation. To do so, you just prepend the variable with a $
. More complex expressions must be wrapped with curly braces: "${user.name} logged in"
.
Equality and Comparison Operators#
Kotlin’s operators to formulate conditions are the following: