2. Motivation
Android core app quality: the app does not crash, force
close, freeze, or otherwise function abnormally on any
targeted device.
3. Motivation
Android core app quality: the app does not crash, force
close, freeze, or otherwise function abnormally on any
targeted device.
4. JSR-305, Android Support Annotations
@Nonnull
@Override
public User save(@Nonnull User user) {
// ...
userDao.save(user);
// ...
return user;
}
5. JSR-305, Android Support Annotations
1. Hard to maintain.
2. Verbose, but could be simplified using @ParametersAreNonnullByDefault or
@ParametersAreNullableByDefault.
3. Just warning.
4. “Leak” NPE.
5. ~6500 in SBOL.
9. Here comes Kotlin
fun main(args: Array<String>) {
val hello = "Hello, Innopolis!"
println(hello)
}
10. Here comes Kotlin
● statically-typed, object-oriented, functional;
● target: JVM, Android, JS, Native (in progress);
● fully interoperable with Java;
● compact runtime lib, good tooling;
● runs as fast as an equivalent on Java;
● easy to learn for Java developers;
● official Android development language.
11. Not nullable types by default
var foo: String = "Foo" // var foo = "Foo"
foo = null // Compile error: Null can not be a value of a non-null type String
var bar: String? = "Bar"
bar = null // Ok
bar = foo // Ok
foo = bar // Error
13. Deal with nullable types
val user: User? = null
println(user.address.street)
// Error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable
receiver of type kotlin.String?
14. Smartcast
val user: User? = null
if (user != null && user.address != null) {
println(user.address.street) // Now: user: User, address: Address
}
User?
User
Address?
Address
15. Safe call operator ?.
val user: User? = null
println(user?.address)
if (user != null) {
return user.getAddress();
} else {
return null;
}
user?.address
user.address
null
*Kotlin in Action
user != null
user == null
Safe call operator always returns
nullable type of <T>, so <T> result type
transform to type <T?>
println(user?.address?.street)
Chaining safe call operators:
16. Elvis operator ?:
val user: User? = null
println(user ?: ADMIN)
if (user != null) {
return user;
} else {
return ADMIN;
}
user
user
ADMIN
*Kotlin in Action
user != null
user == null
println(user?.address?.street ?: UNKNOWN_STREET)
17. Let function
val user: User? = null
user?.let { println(it) }
if (user != null) {
System.out.println(user);
}
user
println(user)
user != null
*Kotlin in Action
18. Not null assertions: !! operator
val user: User? = null
println(user!!.address)
System.out.println(user.getAddress());
user
user.address
NullPointerException
*Kotlin in Action
user != null
user == null
19. Platform types and Java interoperability
Java Kotlin
@Nullable + String String?
@NotNull + String String
String String!
String! = String or String?
val stringValue = Java.getString()
println(stringValue.length) // Ok
println(stringValue?.length) // Ok
20. Kotlin nullability: Examples
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val id = savedInstanceState.getString(ID) // compile error
}
}
class MyIntentService : IntentService("MyIntentService") {
override fun onHandleIntent(intent: Intent?) {
val param1 = intent.getStringExtra(EXTRA_PARAM1) // compile error
}
}
21. Intrinsics
● Apply Intrinsics.checkParameterIsNotNull() for every public function for each
non-null parameter.
● Disable using -Xno-param-assertions or Proguard.
JDK 1.8 Kotlin
@Override
public void forEachRemaining(DoubleConsumer
action) {
Objects.requireNonNull(action);
if (count == -2) {
action.accept(first);
count = -1;
}
}
@NotNull
public User save(@NotNull User user) {
Intrinsics.checkParameterIsNotNull(user, "user");
this.userDao.save(user);
return user;
}
22. Kotlin nullability
1. Hard to maintain built-in type system.
2. Verbose special syntax for nullable values.
3. Not error, just a warning, no guarantees compile time error.
4. “Leak” NPE kotlin intrinsics.
5. GC overhead no overhead at all.
6. Problem with third-party libraries kotlin compiler could read default java
annotations from external byte code.
23. Extension functions
Java Kotlin
public static boolean isEmpty(@Nullable String string) {
return string == null || string.isEmpty();
}
fun String?.isEmpty(): Boolean {
return this == null || this.length == 0
}
String text = ...;
if (isEmpty(text)) {
System.out.println("Empty text!");
}
val text = ...
if (text.isEmpty()) {
println("Empty text!")
}
24. Extension functions: Lambdas
fun String.printWithCondition(predicate: (s: String) -> Boolean) {
if (predicate(this)) {
println(this)
}
}
val text = "Hello"
text.printWithCondition { it == "Hello" }
25. Extension functions: Lambdas with inline
inline fun String.printWithCondition(predicate: (s: String) -> Boolean) {
if (predicate(this)) {
println(this)
}
}
val text = "Hello"
text.printWithCondition { it == "Hello" }
String text = "Hello";
if(Intrinsics.areEqual(text, "Hello")) {
System.out.println(text);
}
26. Extension functions: AutoCloseable
val fos = FileOutputStream("data.txt")
val result = fos.use {
// do some stuff with stream
"result"
}
println(result)
val resultSet: ResultSet? = ...
resultSet?.use {
println(it.getString(USER_ID))
}
27. Extension functions: Collections
val list = listOf("Foo", "Bar", "Buzz")
list.filter { it.startsWith("B") } // [Bar, Buzz]
list.map { it.toUpperCase() } // [FOO, BAR, BUZZ]
list.flatMap { it.asIterable() } // [F, o, o, B, a, r, B, u, z, z]
list.groupBy { it.first() } // {F=[Foo], B=[Bar, Buzz]}
list.fold(0, { acc, s -> acc + s.length }) // 10
list.reduce { acc, s -> s + acc } // BuzzBarFoo
28. Extension functions: Collections
1. Immutable by default.
2. Mutable collections should be created explicitly, e.g. by mutableListOf(),
mutableSetOf(), mutableMapOf() or using constructors.
3. Not lazy by default: each transformation → new collection.
4. Sequences are lazy like a Java 8 Streams. No parallelism.
5. Default implementations: ArrayList, HashSet and HashMap.
6. Array supports same functional operators.
29. Extension functions: Lambda Extensions
inline fun String.printWithCondition(predicate: String.() -> Boolean) {
if (predicate()) { // predicate(this)
println(this)
}
}
val text = "Hello"
text.printWithCondition { length > 3 }
30. Extension functions: Standard functions
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
val user = User().apply {
id = 1L
name = "John Smith"
}
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
user?.let {
println(user.name)
}
31. Conclusion: tools
1. Dagger 2, Butterknife, RxJava 2, Retrofit 2, Realm, Room...
2. Built-in plugin in AS 3.0.
3. Static analysis - https://github.com/arturbosch/detekt.
4. https://kotlinlang.org/docs/reference/coding-conventions.html.
5. Proguard - ok.
6. Debugging - as java.
7. Compile speed - as java - https://habrahabr.ru/company/badoo/blog/329026/.
8. Java projects: Spring 5, Reactor, Corda, Gradle, Spark.
9. Android projects: Hotellook, Avito.
32. Conclusion: next
1. Intro to Kotlin at Google IO 17: https://youtu.be/X1RVYt2QKQE.
2. Jake Wharton and Christina Lee at Google IO 17:
https://youtu.be/fPzxfeDJDzY.
3. https://developer.android.com/kotlin/index.html.
4. https://kotlinlang.org/docs/reference/.
5. 10 Kotlin Tricks in 10 ish minutes by Jake Wharton:
https://youtu.be/0sPzDwS55wM.
6. Kotlin in Action: https://www.manning.com/books/kotlin-in-action.
7. Kotlin type system: http://natpryce.com/articles/000818.html.
8. Perfomance: https://goo.gl/J2FVSm and https://goo.gl/CDKxw9.