SlideShare a Scribd company logo
Kotlin vs. Java
Some Java issues addressed in Kotlin
Kotlin fixes a series of issues that Java suffers from
— Null references are controlled by the type system.
— No raw types
— Arrays in Kotlin are invariant
— Kotlin has proper function types, as opposed to Java's SAM-conversions
— Use-site variance without wildcards
— Kotlin does not have checked exceptions
Null references are controlled by the
type system
https://kotlinlang.org/docs/reference/null-safety.html
Nullable types and Non-Null Types
var a: String = "abc"
a = null // compilation error
To allow nulls, we can declare a
variable as nullable string, written
String?
var b: String? = "abc"
b = null // ok
val l = a.length
val l = b.length // error: variable 'b' can
be null
Checking for null in conditions
val l = if (b != null) b.length else -1 if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
Safe Calls
b?.length
This returns b.length if b is not null,
and null otherwise. The type of this
expression is Int?
bob?.department?.head?.name
Such a chain returns null if any of the
properties in it is null
Elvis Operator
When we have a nullable reference r,
we can say "if r is not null, use it,
otherwise use some non-null value x"
val l: Int = if (b != null) b.length else -1
Along with the complete
if-expression, this can be expressed
with the Elvis operator, written ?:
val l = b?.length ?: -1
The !! Operator
We can write b!!, and this will return a
non-null value of b or throw an NPE if
b is null
val l = b!!.length
If you want an NPE, you can have it,
but you have to ask for it explicitly,
and it does not appear out of the blue
Safe Casts
Regular casts may result into a
ClassCastException if the object is not
of the target type
Another option is to use safe casts
that return null if the attempt was not
successful
val aInt: Int? = a as? Int
Collections of Nullable Type
If you have a collection of
elements of a nullable type and
want to filter non-null elements,
you can do so by using
filterNotNull
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
No raw types
Existing Java code can be called from Kotlin in a natural way, and Kotlin code
can be used from Java rather smoothly as well
Getters and Setters
Methods that follow the Java conventions for
getters and setters are represented as properties
in Kotlin
Boolean accessor methods are represented as
properties which have the same name as the
getter method
Note that, if the Java class only has a setter, it
will not be visible as a property in Kotlin, because
Kotlin does not support set-only properties at this
time
Methods returning void
If a Java method returns void, it will return Unit when called from Kotlin
Null-Safety and Platform Types
val list = ArrayList<String>() // non-null (constructor result)
list.add("Item")
val size = list.size // non-null (primitive int)
val item = list[0] // platform type inferred (ordinary Java object)
item.substring(1) // allowed, may throw an exception if item == null
val nullable: String? = item // allowed, always works
val notNull: String = item // allowed, may fail at runtime
Mapped types
Java type Kotlin type
byte kotlin.Byte
short kotlin.Short
int kotlin.Int
long kotlin.Long
char kotlin.Char
float kotlin.Float
double kotlin.Double
boolean kotlin.Boolean
Java type Kotlin type
java.lang.Object kotlin.Any!
java.lang.Cloneable kotlin.Cloneable!
java.lang.Comparable kotlin.Comparable!
java.lang.Enum kotlin.Enum!
java.lang.Annotation kotlin.Annotation!
java.lang.Deprecated kotlin.Deprecated!
java.lang.CharSequence kotlin.CharSequence!
java.lang.String kotlin.String!
java.lang.Number kotlin.Number!
java.lang.Throwable kotlin.Throwable!
Mapped types
Java type Kotlin type
java.lang.Byte kotlin.Byte?
java.lang.Short kotlin.Short?
java.lang.Integer kotlin.Int?
java.lang.Long kotlin.Long?
java.lang.Character kotlin.Char?
java.lang.Float kotlin.Float?
java.lang.Double kotlin.Double?
java.lang.Boolean kotlin.Boolean?
Java type Kotlin type
int[] kotlin.IntArray!
String[] kotlin.Array<(out) String>!
Java type Kotlin read-only
type
Kotlin mutable type Loaded platform type
Iterator<T> Iterator<T> MutableIterator<T> (Mutable)Iterator<T>!
Iterable<T> Iterable<T> MutableIterable<T> (Mutable)Iterable<T>!
Collection<T> Collection<T> MutableCollection<T> (Mutable)Collection<T>!
Set<T> Set<T> MutableSet<T> (Mutable)Set<T>!
List<T> List<T> MutableList<T> (Mutable)List<T>!
ListIterator<T> ListIterator<T> MutableListIterator<T> (Mutable)ListIterator<T>!
Map<K, V> Map<K, V> MutableMap<K, V> (Mutable)Map<K, V>!
Map.Entry<K, V> Map.Entry<K, V> MutableMap.MutableEnt
ry<K,V>
(Mutable)Map.(Mutable)En
try<K, V>!
Mapped types
Java generics in Kotlin
Foo<? extends Bar>
Foo<? super Bar>
List
Foo<out Bar!>!
Foo<in Bar!>!
List<*>!, i.e. List<out Any?>!.
if (a is List<Int>) // Error: cannot check if it is really a List of Ints
// but
if (a is List<*>) // OK: no guarantees about the contents of the list
Java Arrays
Arrays in Kotlin are invariant, unlike Java.
There are specialized classes for every type of primitive array (IntArray,
DoubleArray, CharArray, and so on) for maximum performance.
Java Varargs
public class JavaArrayExample {
public void removeIndicesVarArg(int... indices) {
// code here...
}
}
In that case you need to use the spread operator * to pass
the IntArray:
val javaObj = JavaArrayExample()
val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndicesVarArg(*array)
It's currently not possible to pass null to
a method that is declared as varargs.
Inheritance from Java classes
At most one Java class (and as many Java interfaces as you like) can be a
supertype for a class in Kotlin.
Accessing static members
Static members of Java classes form "companion objects" for these classes. We
cannot pass such a "companion object" around as a value, but can access the
members explicitly, for example:
if (Character.isLetter(a)) {
// ...
}
Arrays in Kotlin are invariant
https://kotlinlang.org/docs/reference/basic-types.html#arrays
Class Array
class Array<T> private constructor() {
val size: Int
operator fun get(index: Int): T
operator fun set(index: Int, value: T): Unit
operator fun iterator(): Iterator<T>
// ...
}
Create an Array
arrayOf(1, 2, 3) creates an array [1, 2, 3]
Alternatively, the arrayOfNulls() library function can be used to create an array of a
given size filled with null elements
// Creates an Array<String> with values ["0", "1", "4", "9", "16"]
val asc = Array(5, { i -> (i * i).toString() })
Unlike Java, arrays in Kotlin are invariant
This means that Kotlin does not let us assign an Array<String> to an Array<Any>,
which prevents a possible runtime failure
But you can use Array<out Any>
Classes to represent arrays of primitive types
— ByteArray
— ShortArray
— IntArray
— and so on
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
Kotlin has proper function types, as
opposed to Java's SAM-conversions
Higher-Order Functions
fun <T> lock(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
}
finally {
lock.unlock()
}
}
Function Types
fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? {
var max: T? = null
for (it in collection)
if (max == null || less(max, it))
max = it
return max
}
Use-site variance without wildcards
Generics
class Box<T>(t: T) {
var value = t
}
To create an instance of such a class, we need to provide the type arguments:
val box: Box<Int> = Box<Int>(1)
Variance
One of the most tricky parts of Java's type system is wildcard types
And Kotlin doesn't have any
Instead, it has two other things:
● declaration-site variance
● type projections
Declaration-site variance (variance annotation out)
interface Source<T> {
T nextT();
}
void demo(Source<String> strs) {
Source<Object> objects = strs; // !!! Not
allowed in Java
// ...
}
abstract class Source<out T> {
abstract fun nextT(): T
}
fun demo(strs: Source<String>) {
val objects: Source<Any> = strs // This
is OK, since T is an out-parameter
// ...
}
Declaration-site variance (variance annotation in)
abstract class Comparable<in T> {
abstract fun compareTo(other: T): Int
}
fun demo(x: Comparable<Number>) {
x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number
// Thus, we can assign x to a variable of type Comparable<Double>
val y: Comparable<Double> = x // OK!
}
Use-site variance: Type projections
class Array<T>(val size: Int) {
fun get(index: Int): T { /* ... */ }
fun set(index: Int, value: T) { /* ... */ }
}
fun copy(from: Array<Any>, to: Array<Any>) {
assert(from.size == to.size)
for (i in from.indices)
to[i] = from[i]
}
val ints: Array<Int> = arrayOf(1, 2, 3)
val any = Array<Any>(3) { "" }
copy(ints, any) // Error: expects (Array<Any>, Array<Any>).
fun copy(from: Array<out Any>, to: Array<Any>) {
// ...
}
Star-projection syntax
— For Foo<out T>, where T is a covariant type parameter with the upper bound
TUpper, Foo<*> is equivalent to Foo<out TUpper>. It means that when the T
is unknown you can safely read values of TUpper from Foo<*>
— For Foo<in T>, where T is a contravariant type parameter, Foo<*> is
equivalent to Foo<in Nothing>. It means there is nothing you can write to
Foo<*> in a safe way when T is unknown
— For Foo<T>, where T is an invariant type parameter with the upper bound
TUpper, Foo<*> is equivalent to Foo<out TUpper> for reading values and to
Foo<in Nothing> for writing values
If a generic type has several type parameters each of them can be projected
independently. For example, if the type is declared as interface Function<in
T, out U> we can imagine the following star-projections:
— Function<*, String> means Function<in Nothing, String>
— Function<Int, *> means Function<Int, out Any?>
— Function<*, *> means Function<in Nothing, out Any?>
Generic functions
Not only classes can have type parameters. Functions can, too:
fun <T> singletonList(item: T): List<T> {
// ...
}
fun <T> T.basicToString() : String { // extension function
// ...
}
To call a generic function, specify the type arguments at the call site after the
name of the function:
val l = singletonList<Int>(1)
Kotlin does not have checked
exceptions
https://kotlinlang.org/docs/reference/exceptions.html
Checked Exceptions
The following is an example interface of the JDK implemented by StringBuilder
class:
Appendable append(CharSequence csq) throws IOException;
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}

More Related Content

What's hot (20)

PPTX
Java seminar
devendrakhairwa
 
PDF
Data Persistence in Android with Room Library
Reinvently
 
PDF
An Introduction to Gradle for Java Developers
Kostas Saidis
 
PDF
Try Jetpack Compose
LutasLin
 
PDF
Kotlin vs Java | A Comparative Analysis | IDEA USHER
Nitish Garg
 
PPTX
Android Development with Kotlin course
GoogleDevelopersLeba
 
PDF
Kotlin for Android Development
Speck&Tech
 
PDF
A quick and fast intro to Kotlin
XPeppers
 
PPT
The Kotlin Programming Language
intelliyole
 
PPTX
Training on Core java | PPT Presentation | Shravan Sanidhya
Shravan Sanidhya
 
PPTX
Introduction to kotlin and OOP in Kotlin
vriddhigupta
 
PDF
Introduction to kotlin
NAVER Engineering
 
PPT
Java basic
Sonam Sharma
 
PPTX
Introduction to Kotlin for Android developers
Mohamed Wael
 
PDF
Introduction to Java 11
Knoldus Inc.
 
PPSX
Kotlin Language powerpoint show file
Saurabh Tripathi
 
ODP
Groovy intro
NexThoughts Technologies
 
PPTX
Kotlin
Ravi Pawar
 
PDF
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
Hardik Trivedi
 
PPTX
Kotlin Basics & Introduction to Jetpack Compose.pptx
takshilkunadia
 
Java seminar
devendrakhairwa
 
Data Persistence in Android with Room Library
Reinvently
 
An Introduction to Gradle for Java Developers
Kostas Saidis
 
Try Jetpack Compose
LutasLin
 
Kotlin vs Java | A Comparative Analysis | IDEA USHER
Nitish Garg
 
Android Development with Kotlin course
GoogleDevelopersLeba
 
Kotlin for Android Development
Speck&Tech
 
A quick and fast intro to Kotlin
XPeppers
 
The Kotlin Programming Language
intelliyole
 
Training on Core java | PPT Presentation | Shravan Sanidhya
Shravan Sanidhya
 
Introduction to kotlin and OOP in Kotlin
vriddhigupta
 
Introduction to kotlin
NAVER Engineering
 
Java basic
Sonam Sharma
 
Introduction to Kotlin for Android developers
Mohamed Wael
 
Introduction to Java 11
Knoldus Inc.
 
Kotlin Language powerpoint show file
Saurabh Tripathi
 
Kotlin
Ravi Pawar
 
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
Hardik Trivedi
 
Kotlin Basics & Introduction to Jetpack Compose.pptx
takshilkunadia
 

Similar to 1 kotlin vs. java: some java issues addressed in kotlin (20)

PDF
2 kotlin vs. java: what java has that kotlin does not
Sergey Bandysik
 
PPTX
Flexible Types in Kotlin - JVMLS 2015
Andrey Breslav
 
PDF
Kotlin: Challenges in JVM language design
Andrey Breslav
 
PDF
Kotlin: a better Java
Nils Breunese
 
PDF
Kotlin Introduction with Android applications
Thao Huynh Quang
 
PDF
Kotlin what_you_need_to_know-converted event 4 with nigerians
junaidhasan17
 
PDF
Intro to Kotlin
Magda Miu
 
PDF
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Codemotion
 
PDF
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Сбертех | SberTech
 
PDF
Having Fun with Kotlin Android - DILo Surabaya
DILo Surabaya
 
PDF
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
Andrey Breslav
 
PDF
Kotlin: forse è la volta buona (Trento)
Davide Cerbo
 
PDF
Privet Kotlin (Windy City DevFest)
Cody Engel
 
PDF
Kotlin- Basic to Advance
Coder Tech
 
PDF
Kotlin
Nodirbek Usmanov
 
PDF
Kotlin intro
Elifarley Cruz
 
PDF
Little Helpers for Android Development with Kotlin
Kai Koenig
 
PPTX
Hello kotlin | An Event by DSC Unideb
Muhammad Raza
 
PDF
Exploring Kotlin
Johan Haleby
 
PDF
Kotlin: A pragmatic language by JetBrains
Jigar Gosar
 
2 kotlin vs. java: what java has that kotlin does not
Sergey Bandysik
 
Flexible Types in Kotlin - JVMLS 2015
Andrey Breslav
 
Kotlin: Challenges in JVM language design
Andrey Breslav
 
Kotlin: a better Java
Nils Breunese
 
Kotlin Introduction with Android applications
Thao Huynh Quang
 
Kotlin what_you_need_to_know-converted event 4 with nigerians
junaidhasan17
 
Intro to Kotlin
Magda Miu
 
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Codemotion
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Сбертех | SberTech
 
Having Fun with Kotlin Android - DILo Surabaya
DILo Surabaya
 
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
Andrey Breslav
 
Kotlin: forse è la volta buona (Trento)
Davide Cerbo
 
Privet Kotlin (Windy City DevFest)
Cody Engel
 
Kotlin- Basic to Advance
Coder Tech
 
Kotlin intro
Elifarley Cruz
 
Little Helpers for Android Development with Kotlin
Kai Koenig
 
Hello kotlin | An Event by DSC Unideb
Muhammad Raza
 
Exploring Kotlin
Johan Haleby
 
Kotlin: A pragmatic language by JetBrains
Jigar Gosar
 
Ad

1 kotlin vs. java: some java issues addressed in kotlin

  • 1. Kotlin vs. Java Some Java issues addressed in Kotlin
  • 2. Kotlin fixes a series of issues that Java suffers from — Null references are controlled by the type system. — No raw types — Arrays in Kotlin are invariant — Kotlin has proper function types, as opposed to Java's SAM-conversions — Use-site variance without wildcards — Kotlin does not have checked exceptions
  • 3. Null references are controlled by the type system https://kotlinlang.org/docs/reference/null-safety.html
  • 4. Nullable types and Non-Null Types var a: String = "abc" a = null // compilation error To allow nulls, we can declare a variable as nullable string, written String? var b: String? = "abc" b = null // ok val l = a.length val l = b.length // error: variable 'b' can be null
  • 5. Checking for null in conditions val l = if (b != null) b.length else -1 if (b != null && b.length > 0) { print("String of length ${b.length}") } else { print("Empty string") }
  • 6. Safe Calls b?.length This returns b.length if b is not null, and null otherwise. The type of this expression is Int? bob?.department?.head?.name Such a chain returns null if any of the properties in it is null
  • 7. Elvis Operator When we have a nullable reference r, we can say "if r is not null, use it, otherwise use some non-null value x" val l: Int = if (b != null) b.length else -1 Along with the complete if-expression, this can be expressed with the Elvis operator, written ?: val l = b?.length ?: -1
  • 8. The !! Operator We can write b!!, and this will return a non-null value of b or throw an NPE if b is null val l = b!!.length If you want an NPE, you can have it, but you have to ask for it explicitly, and it does not appear out of the blue
  • 9. Safe Casts Regular casts may result into a ClassCastException if the object is not of the target type Another option is to use safe casts that return null if the attempt was not successful val aInt: Int? = a as? Int
  • 10. Collections of Nullable Type If you have a collection of elements of a nullable type and want to filter non-null elements, you can do so by using filterNotNull val nullableList: List<Int?> = listOf(1, 2, null, 4) val intList: List<Int> = nullableList.filterNotNull()
  • 11. No raw types Existing Java code can be called from Kotlin in a natural way, and Kotlin code can be used from Java rather smoothly as well
  • 12. Getters and Setters Methods that follow the Java conventions for getters and setters are represented as properties in Kotlin Boolean accessor methods are represented as properties which have the same name as the getter method Note that, if the Java class only has a setter, it will not be visible as a property in Kotlin, because Kotlin does not support set-only properties at this time
  • 13. Methods returning void If a Java method returns void, it will return Unit when called from Kotlin
  • 14. Null-Safety and Platform Types val list = ArrayList<String>() // non-null (constructor result) list.add("Item") val size = list.size // non-null (primitive int) val item = list[0] // platform type inferred (ordinary Java object) item.substring(1) // allowed, may throw an exception if item == null val nullable: String? = item // allowed, always works val notNull: String = item // allowed, may fail at runtime
  • 15. Mapped types Java type Kotlin type byte kotlin.Byte short kotlin.Short int kotlin.Int long kotlin.Long char kotlin.Char float kotlin.Float double kotlin.Double boolean kotlin.Boolean Java type Kotlin type java.lang.Object kotlin.Any! java.lang.Cloneable kotlin.Cloneable! java.lang.Comparable kotlin.Comparable! java.lang.Enum kotlin.Enum! java.lang.Annotation kotlin.Annotation! java.lang.Deprecated kotlin.Deprecated! java.lang.CharSequence kotlin.CharSequence! java.lang.String kotlin.String! java.lang.Number kotlin.Number! java.lang.Throwable kotlin.Throwable!
  • 16. Mapped types Java type Kotlin type java.lang.Byte kotlin.Byte? java.lang.Short kotlin.Short? java.lang.Integer kotlin.Int? java.lang.Long kotlin.Long? java.lang.Character kotlin.Char? java.lang.Float kotlin.Float? java.lang.Double kotlin.Double? java.lang.Boolean kotlin.Boolean? Java type Kotlin type int[] kotlin.IntArray! String[] kotlin.Array<(out) String>!
  • 17. Java type Kotlin read-only type Kotlin mutable type Loaded platform type Iterator<T> Iterator<T> MutableIterator<T> (Mutable)Iterator<T>! Iterable<T> Iterable<T> MutableIterable<T> (Mutable)Iterable<T>! Collection<T> Collection<T> MutableCollection<T> (Mutable)Collection<T>! Set<T> Set<T> MutableSet<T> (Mutable)Set<T>! List<T> List<T> MutableList<T> (Mutable)List<T>! ListIterator<T> ListIterator<T> MutableListIterator<T> (Mutable)ListIterator<T>! Map<K, V> Map<K, V> MutableMap<K, V> (Mutable)Map<K, V>! Map.Entry<K, V> Map.Entry<K, V> MutableMap.MutableEnt ry<K,V> (Mutable)Map.(Mutable)En try<K, V>! Mapped types
  • 18. Java generics in Kotlin Foo<? extends Bar> Foo<? super Bar> List Foo<out Bar!>! Foo<in Bar!>! List<*>!, i.e. List<out Any?>!. if (a is List<Int>) // Error: cannot check if it is really a List of Ints // but if (a is List<*>) // OK: no guarantees about the contents of the list
  • 19. Java Arrays Arrays in Kotlin are invariant, unlike Java. There are specialized classes for every type of primitive array (IntArray, DoubleArray, CharArray, and so on) for maximum performance.
  • 20. Java Varargs public class JavaArrayExample { public void removeIndicesVarArg(int... indices) { // code here... } } In that case you need to use the spread operator * to pass the IntArray: val javaObj = JavaArrayExample() val array = intArrayOf(0, 1, 2, 3) javaObj.removeIndicesVarArg(*array) It's currently not possible to pass null to a method that is declared as varargs.
  • 21. Inheritance from Java classes At most one Java class (and as many Java interfaces as you like) can be a supertype for a class in Kotlin.
  • 22. Accessing static members Static members of Java classes form "companion objects" for these classes. We cannot pass such a "companion object" around as a value, but can access the members explicitly, for example: if (Character.isLetter(a)) { // ... }
  • 23. Arrays in Kotlin are invariant https://kotlinlang.org/docs/reference/basic-types.html#arrays
  • 24. Class Array class Array<T> private constructor() { val size: Int operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> // ... }
  • 25. Create an Array arrayOf(1, 2, 3) creates an array [1, 2, 3] Alternatively, the arrayOfNulls() library function can be used to create an array of a given size filled with null elements // Creates an Array<String> with values ["0", "1", "4", "9", "16"] val asc = Array(5, { i -> (i * i).toString() })
  • 26. Unlike Java, arrays in Kotlin are invariant This means that Kotlin does not let us assign an Array<String> to an Array<Any>, which prevents a possible runtime failure But you can use Array<out Any>
  • 27. Classes to represent arrays of primitive types — ByteArray — ShortArray — IntArray — and so on val x: IntArray = intArrayOf(1, 2, 3) x[0] = x[1] + x[2]
  • 28. Kotlin has proper function types, as opposed to Java's SAM-conversions
  • 29. Higher-Order Functions fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body() } finally { lock.unlock() } }
  • 30. Function Types fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? { var max: T? = null for (it in collection) if (max == null || less(max, it)) max = it return max }
  • 32. Generics class Box<T>(t: T) { var value = t } To create an instance of such a class, we need to provide the type arguments: val box: Box<Int> = Box<Int>(1)
  • 33. Variance One of the most tricky parts of Java's type system is wildcard types And Kotlin doesn't have any Instead, it has two other things: ● declaration-site variance ● type projections
  • 34. Declaration-site variance (variance annotation out) interface Source<T> { T nextT(); } void demo(Source<String> strs) { Source<Object> objects = strs; // !!! Not allowed in Java // ... } abstract class Source<out T> { abstract fun nextT(): T } fun demo(strs: Source<String>) { val objects: Source<Any> = strs // This is OK, since T is an out-parameter // ... }
  • 35. Declaration-site variance (variance annotation in) abstract class Comparable<in T> { abstract fun compareTo(other: T): Int } fun demo(x: Comparable<Number>) { x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number // Thus, we can assign x to a variable of type Comparable<Double> val y: Comparable<Double> = x // OK! }
  • 36. Use-site variance: Type projections class Array<T>(val size: Int) { fun get(index: Int): T { /* ... */ } fun set(index: Int, value: T) { /* ... */ } } fun copy(from: Array<Any>, to: Array<Any>) { assert(from.size == to.size) for (i in from.indices) to[i] = from[i] } val ints: Array<Int> = arrayOf(1, 2, 3) val any = Array<Any>(3) { "" } copy(ints, any) // Error: expects (Array<Any>, Array<Any>). fun copy(from: Array<out Any>, to: Array<Any>) { // ... }
  • 37. Star-projection syntax — For Foo<out T>, where T is a covariant type parameter with the upper bound TUpper, Foo<*> is equivalent to Foo<out TUpper>. It means that when the T is unknown you can safely read values of TUpper from Foo<*> — For Foo<in T>, where T is a contravariant type parameter, Foo<*> is equivalent to Foo<in Nothing>. It means there is nothing you can write to Foo<*> in a safe way when T is unknown — For Foo<T>, where T is an invariant type parameter with the upper bound TUpper, Foo<*> is equivalent to Foo<out TUpper> for reading values and to Foo<in Nothing> for writing values
  • 38. If a generic type has several type parameters each of them can be projected independently. For example, if the type is declared as interface Function<in T, out U> we can imagine the following star-projections: — Function<*, String> means Function<in Nothing, String> — Function<Int, *> means Function<Int, out Any?> — Function<*, *> means Function<in Nothing, out Any?>
  • 39. Generic functions Not only classes can have type parameters. Functions can, too: fun <T> singletonList(item: T): List<T> { // ... } fun <T> T.basicToString() : String { // extension function // ... } To call a generic function, specify the type arguments at the call site after the name of the function: val l = singletonList<Int>(1)
  • 40. Kotlin does not have checked exceptions https://kotlinlang.org/docs/reference/exceptions.html
  • 41. Checked Exceptions The following is an example interface of the JDK implemented by StringBuilder class: Appendable append(CharSequence csq) throws IOException; try { log.append(message) } catch (IOException e) { // Must be safe }