SlideShare a Scribd company logo
KOTLIN AFTER 9 MONTHS
André Luiz Cardoso
Thiago “Fred" Porciúncula
Kotlin After 9 Months
Kotlin | What is it?
- JetBrains
- JVM
- Concise, Safe, Versatile, Interoperable
44
GAINS
Gains | Synthetic properties
closeButton = (Button) findViewById(R.id.close_button);

closeButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

presenter.close();

}

});
Gains | Synthetic properties
closeButton = findViewById(R.id.close_button);

closeButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

presenter.close();

}

});
Gains | Synthetic properties
closeButton.setOnClickListener { presenter.close() }
Gains | Lambdas
moviesApi.loadMovies(genre)

.map { it.movies }
.map { it.rating > 4 }

.subscribe({ goodMovies ->

goodMovies?.let { view.showMovies(it) }

}, {

Log.e(TAG, "Error loading movies from $genre", it)

})
Gains | Collections
movies.filter { it.isFavorite }
movies.sortedWith(compareBy(
Movie::year, Movie::title, Movie::rating))
val movies = listOf("ET", “Scream")
val rating = listOf(5, 1)
print(movies.zip(rating))
//[(ET, 5), (Tomates Assassinos, 1)]
Gains | Collections
var horrorMoviesTitles = movies
.asSequence()
.filter { it.genre == "horror" }
.map { it.title }
.toList()
Gains | Null safety
public String getUrl(Movie movie) {

if (movie == null || movie.getPosters() == null) {

return fallbackUrl;

}



for (Poster poster : movie.getPosters()) {

if (poster.type.equals("P") && poster.getUrl() != null) {

return poster.getUrl();

}

}



return fallbackUrl;

}
Gains | Null safety
val url =
movie?.posters?.find { it.type == "P" }?.url ?: fallbackUrl
Gains | Extension functions
val Context.isLandscape: Boolean get() =
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
fun View.fadeIn() {

visibility = View.VISIBLE

ViewCompat.animate(this)

.alpha(1F)

.start(

}
var View.visible: Boolean

get() = visibility == View.VISIBLE

set(value) {

visibility = if (value) View.VISIBLE else View.GONE

}
Gains | Extension functions
val Context.isLandscape: Boolean get() =
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
fun View.fadeIn() {

visibility = View.VISIBLE

ViewCompat.animate(this)

.alpha(1F)

.start(

}
var View.visible: Boolean

get() = visibility == View.VISIBLE

set(value) {

visibility = if (value) View.VISIBLE else View.GONE

}
Gains | Extension functions
val Context.isLandscape: Boolean get() =
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
fun View.fadeIn() {

visibility = View.VISIBLE

ViewCompat.animate(this)

.alpha(1F)

.start(

}
var View.visible: Boolean

get() = visibility == View.VISIBLE

set(value) {

visibility = if (value) View.VISIBLE else View.GONE

}
Gains | Interoperability
Glide

.with(this)

.load(url)

.diskCacheStrategy(DiskCacheStrategy.SOURCE)

.error(R.drawable.default_poster)

.into(posterImageView)
Gains | Interoperability
// MovieExtensions.kt

fun Movie.isNew(currentDate: Date): Boolean {

return launchDate?.let { it.daysBefore(currentDate) < 7 } ?: false

}
// SomeFile.java
boolean isNew = MovieExtensions.isNew(movie);
Gains | Data classes
data class Movie(
val title: String, 

val year: Int,
val rating: Float
)
val et = Movie(title = "ET", year = 1982, rating = 5.0f)
val (title, year) = et
moviesSet.add(et)
Gains | Immutability
val movies = mutableListOf<Movie>()
movies.add(et)
val immutableMovies = listOf<Movie>()
immutableMovies.add(et)
var movie = et
movie = et.copy(title = "Alien")
Gains | Sealed classes
sealed class MovieViewState {
data class Loaded(val movies: List<Movie>): MovieViewState()
class Error: MovieViewState()
class Loading: MovieViewState()
}
Gains | Sealed classes
fun render(viewState: MovieViewState) {
return when(viewState) {
is MovieViewState.Loaded -> print(viewState.movies)
}
}
//'when' expression must be exhaustive, add necessary 'is Error', 'is
Loading' branches or 'else' branch instead
Gains | Multiple classes per file
// MoviesInjection.kt
@ActivityScope

@Subcomponent(modules = arrayOf(MovieModule::class))

interface MovieComponent {

fun inject(activity: MovieActivity)

}



@Module

class MovieModule(private val view: Movie.MovieView) {



@Provides @ActivityScope

fun provideMoviePresenter(movieLoader: MovieLoader): Movie.Presenter {

return MoviePresenter(view, movieLoader)

}

}
Gains | Multiple classes per file
// MoviesMvp.kt
interface MoviesView {
fun showMovies(movies: List<Movie>)
}
interface MoviesPresenter {
fun loadMovies()
}
Gains | Happiness
😃
PAINS
Pains | Build time
Pains | More methods
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
Kotlin After 9 Months
Pains | Crest of the wave
moviesApi.loadMovies(genre)

.map { it.movies }
Pains | Learning
😫
Pains | Abuse
fun Context.checkSelfPermissionCompat(permission: String): Int {

return ContextCompat.checkSelfPermission(this, permission)

}
TIPS
Tips | Starting with Java works
Tips | Avoid writing Kotlin as Java
if (movieTitle == "Guardians of the galaxy") {

movie.setGenre(comedy)

} else if (movieRating > 4) {

movie.setGenre(good)

} else {

movie.setGenre(others)

}
if (movie != null) {

presenter.list(movie.getGenre())

}
Tips | Avoid writing Kotlin as Java
movie.genre = when {

movieTitle == "Guardians of the galaxy" -> comedy
movieRating > 4 -> good
else -> others

}
movie?.let {

presenter.list(it.genre)

}
Tips | JVM annotations
class MovieTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0): TextView(context, attrs, defStyleAttr)
data class Movie(val title: String) : Parcelable {
// ...
companion object {
@JvmField val CREATOR = object: Parcelable.Creator<Movie> {
// ...
}
}
}
Tips | JVM annotations
@file:JvmName(“ExtensionsUtils")
companion object {

@JvmStatic fun newInstance(tourCode: String): Fragment {

// ...

}

}
Tips | Adopt a code standard
class MoviesPresenter(

movies: List<Movie>,

private val moviesApi: MoviesApi,

override val view: Movies.View,

router: Router,

private val user: User,

override val shareManager: ShareManager

): BaseMoviesPresenter(movies, router, user), Movies.Presenter { … }
Tips | Adopt a code standard
@file:JvmName(“ImageFormatUtil”)
…
ImageFormatUtil.isGif(file);
vs
@file:JvmName(“ImageFormatUtil”)
…
ImageFormatUtilKt.isGif(file);
Tips | Adopt a code standard
titleTextView.text = movie.title
vs
title_text_view.text = movie.title
Tips | Adopt a code standard
import kotlinx.android.synthetic.main.movie_activity.title_text_view
as titleTextView
Tips | Utils turn into extensions
fun Date?.format(pattern: String): String {

return this?.let { SimpleDateFormat(pattern, Locale.US).format(it) } ?: ""

}
public class DateUtils {

public String format(Date date, String pattern) {

if (date == null) {

return "";

}

return new SimpleDateFormat(pattern, Locale.US).format(date);

}

}
Tips | Watch out for nulls coming from Java
val movie = Movie() // Classe Java


movie.genre = null

movie.genre.toString() // NPE
Tips | Null annotations
// Java

public static void prettyPrint(@NonNull String message) {

System.out.print(message);

}



public @Nullable Rating getRating() { … }
// Kotlin

prettyPrint(null)

val x: Rating = Test.getRating()
Tips | Null annotations
// Java

public static void prettyPrint(@NonNull String message) {

System.out.print(message);

}



public @Nullable Rating getRating() { … }
// Kotlin

prettyPrint("oi")

val x: Rating? = Test.getRating()
Tips | Null annotations
@javax.annotation.ParametersAreNonnullByDefault
package com.arctouch.movies;
Tips | Named parameters
val view = LayoutInflater.from(parent.context).inflate(

resource = R.layout.listitem_diagram_showcase_category,

root = parent,

attachToRoot = false)
Tips | Builders
val movie = Movie(

title = "Back to the Future 4",

year = 2030,

rating = 5f

)



val movie = Movie().apply {

title = "Back to the Future 4"

year = 2030

rating = 5f

}
Tips | Interface default implementations
// Kotlin
interface MovieHandler {
fun handleMovie() {
print("default handling")
}
}
// Java
class JavaMovieHandler implements MovieHandler {
}
Tips | Annotation use-site target
data class SomeDataClass(

@field:SomeAnnotation

@get:[Annotation1 Annotation2]

@set:YetAnotherAnnotation

@param:LastAnnotation

var someProperty: SomeType,
…
Tips | Dagger
MoviesComponent.java:38: error:
io.reactivex.Observable<error.NonExistentClass> cannot be provided
without an @Provides- or @Produces-annotated method.
Tips | Java 8 lambda
val map = mapOf("Java" to "Kotlin")
map.forEach { key, value -> print("Java 8") }
map.forEach { (key, value) -> print("Kotlin") }
Tips | Kotlin Standard Library in Java
goodMovies = CollectionsKt.minus(movies, badMovies);
List<Movie> shortMovies =
CollectionsKt.filter(movies, movie -> movie.length() > 100);

shortMoviesTitles =
CollectionsKt.map(shortMovies, Movie::getTitle);
Tips | Unit leaking to Java
// Kotlin

val movieLoadedSubject: Subject<Unit> = PublishSubject.create<Unit>()



movieLoadedSubject.subscribe {

// no arg

}

// Java
movieLoadedSubject.subscribe(unit -> {

// can't ignore Unit arg :(

});
Tips | Less libs
Tips | Less libs
HM… SHOULD WE
REALLY USE IT?
5959
Kotlin After 9 Months
Kotlin After 9 Months
Kotlin After 9 Months
Kotlin After 9 Months
6464
OBRIGADO
We are hiring !

More Related Content

PDF
Clean code with google guava jee conf
PDF
Con5623 pdf 5623_001
PDF
Google Guava & EMF @ GTUG Nantes
PDF
CDI do básico ao avançado
PDF
Deep dive into Oracle ADF
PPTX
Introduction to CDI and DI in Java EE 6
PDF
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
PDF
Clean code with google guava jee conf
Con5623 pdf 5623_001
Google Guava & EMF @ GTUG Nantes
CDI do básico ao avançado
Deep dive into Oracle ADF
Introduction to CDI and DI in Java EE 6
JavaFX Your Way: Building JavaFX Applications with Alternative Languages

What's hot (15)

PDF
Dependency Injection with CDI in 15 minutes
PDF
T.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai University
PDF
Google Guava
PDF
CDI: How do I ?
PDF
guice-servlet
PDF
VJET bringing the best of Java and JavaScript together
PDF
Scalaz 8 vs Akka Actors
PDF
Java objects on steroids
PDF
SOLID Principles
PPTX
Junit 5 - Maior e melhor
PDF
Towards the Cloud: Event-driven Architectures in PHP
PDF
Hidden rocks in Oracle ADF
PPTX
Demystifying dependency Injection: Dagger and Toothpick
PDF
Jumping-with-java8
PDF
Object Design - Part 1
Dependency Injection with CDI in 15 minutes
T.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai University
Google Guava
CDI: How do I ?
guice-servlet
VJET bringing the best of Java and JavaScript together
Scalaz 8 vs Akka Actors
Java objects on steroids
SOLID Principles
Junit 5 - Maior e melhor
Towards the Cloud: Event-driven Architectures in PHP
Hidden rocks in Oracle ADF
Demystifying dependency Injection: Dagger and Toothpick
Jumping-with-java8
Object Design - Part 1
Ad

Similar to Kotlin After 9 Months (20)

PPTX
Kotlin for all the Things
KEY
Android workshop
PDF
Clean code via dependency injection + guice
PDF
Kotlin Generation
PDF
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
PDF
Unittests für Dummies
PDF
November Camp - Spec BDD with PHPSpec 2
PDF
JUnit5 and TestContainers
PDF
Construire une application JavaFX 8 avec gradle
PDF
Kotlin for Android - Vali Iorgu - mRready
PDF
Practical tips for building apps with kotlin
PDF
Singletons in PHP - Why they are bad and how you can eliminate them from your...
PDF
Save time with kotlin in android development
PDF
Desarrollo para Android con Groovy
PPT
Java Performance Tuning
PDF
Java EE 6 CDI Integrates with Spring & JSF
KEY
Javascript unit testing, yes we can e big
PDF
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
PDF
Be pragmatic, be SOLID
PDF
Paging using Paging 3
Kotlin for all the Things
Android workshop
Clean code via dependency injection + guice
Kotlin Generation
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Unittests für Dummies
November Camp - Spec BDD with PHPSpec 2
JUnit5 and TestContainers
Construire une application JavaFX 8 avec gradle
Kotlin for Android - Vali Iorgu - mRready
Practical tips for building apps with kotlin
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Save time with kotlin in android development
Desarrollo para Android con Groovy
Java Performance Tuning
Java EE 6 CDI Integrates with Spring & JSF
Javascript unit testing, yes we can e big
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
Be pragmatic, be SOLID
Paging using Paging 3
Ad

Recently uploaded (20)

PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PPTX
Patient Appointment Booking in Odoo with online payment
PDF
CCleaner 6.39.11548 Crack 2025 License Key
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PPTX
Tech Workshop Escape Room Tech Workshop
PPTX
Introduction to Windows Operating System
PPTX
Computer Software - Technology and Livelihood Education
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PPTX
Trending Python Topics for Data Visualization in 2025
PDF
Website Design Services for Small Businesses.pdf
DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PDF
Salesforce Agentforce AI Implementation.pdf
PDF
Cost to Outsource Software Development in 2025
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PDF
Types of Token_ From Utility to Security.pdf
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Why Generative AI is the Future of Content, Code & Creativity?
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
Patient Appointment Booking in Odoo with online payment
CCleaner 6.39.11548 Crack 2025 License Key
Computer Software and OS of computer science of grade 11.pptx
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
Advanced SystemCare Ultimate Crack + Portable (2025)
Tech Workshop Escape Room Tech Workshop
Introduction to Windows Operating System
Computer Software - Technology and Livelihood Education
DNT Brochure 2025 – ISV Solutions @ D365
Trending Python Topics for Data Visualization in 2025
Website Design Services for Small Businesses.pdf
How to Use SharePoint as an ISO-Compliant Document Management System
Salesforce Agentforce AI Implementation.pdf
Cost to Outsource Software Development in 2025
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
Types of Token_ From Utility to Security.pdf
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev

Kotlin After 9 Months

  • 1. KOTLIN AFTER 9 MONTHS André Luiz Cardoso Thiago “Fred" Porciúncula
  • 3. Kotlin | What is it? - JetBrains - JVM - Concise, Safe, Versatile, Interoperable
  • 4. 44
  • 6. Gains | Synthetic properties closeButton = (Button) findViewById(R.id.close_button);
 closeButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 presenter.close();
 }
 });
  • 7. Gains | Synthetic properties closeButton = findViewById(R.id.close_button);
 closeButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 presenter.close();
 }
 });
  • 8. Gains | Synthetic properties closeButton.setOnClickListener { presenter.close() }
  • 9. Gains | Lambdas moviesApi.loadMovies(genre)
 .map { it.movies } .map { it.rating > 4 }
 .subscribe({ goodMovies ->
 goodMovies?.let { view.showMovies(it) }
 }, {
 Log.e(TAG, "Error loading movies from $genre", it)
 })
  • 10. Gains | Collections movies.filter { it.isFavorite } movies.sortedWith(compareBy( Movie::year, Movie::title, Movie::rating)) val movies = listOf("ET", “Scream") val rating = listOf(5, 1) print(movies.zip(rating)) //[(ET, 5), (Tomates Assassinos, 1)]
  • 11. Gains | Collections var horrorMoviesTitles = movies .asSequence() .filter { it.genre == "horror" } .map { it.title } .toList()
  • 12. Gains | Null safety public String getUrl(Movie movie) {
 if (movie == null || movie.getPosters() == null) {
 return fallbackUrl;
 }
 
 for (Poster poster : movie.getPosters()) {
 if (poster.type.equals("P") && poster.getUrl() != null) {
 return poster.getUrl();
 }
 }
 
 return fallbackUrl;
 }
  • 13. Gains | Null safety val url = movie?.posters?.find { it.type == "P" }?.url ?: fallbackUrl
  • 14. Gains | Extension functions val Context.isLandscape: Boolean get() = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start(
 } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  • 15. Gains | Extension functions val Context.isLandscape: Boolean get() = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start(
 } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  • 16. Gains | Extension functions val Context.isLandscape: Boolean get() = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start(
 } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  • 18. Gains | Interoperability // MovieExtensions.kt
 fun Movie.isNew(currentDate: Date): Boolean {
 return launchDate?.let { it.daysBefore(currentDate) < 7 } ?: false
 } // SomeFile.java boolean isNew = MovieExtensions.isNew(movie);
  • 19. Gains | Data classes data class Movie( val title: String, 
 val year: Int, val rating: Float ) val et = Movie(title = "ET", year = 1982, rating = 5.0f) val (title, year) = et moviesSet.add(et)
  • 20. Gains | Immutability val movies = mutableListOf<Movie>() movies.add(et) val immutableMovies = listOf<Movie>() immutableMovies.add(et) var movie = et movie = et.copy(title = "Alien")
  • 21. Gains | Sealed classes sealed class MovieViewState { data class Loaded(val movies: List<Movie>): MovieViewState() class Error: MovieViewState() class Loading: MovieViewState() }
  • 22. Gains | Sealed classes fun render(viewState: MovieViewState) { return when(viewState) { is MovieViewState.Loaded -> print(viewState.movies) } } //'when' expression must be exhaustive, add necessary 'is Error', 'is Loading' branches or 'else' branch instead
  • 23. Gains | Multiple classes per file // MoviesInjection.kt @ActivityScope
 @Subcomponent(modules = arrayOf(MovieModule::class))
 interface MovieComponent {
 fun inject(activity: MovieActivity)
 }
 
 @Module
 class MovieModule(private val view: Movie.MovieView) {
 
 @Provides @ActivityScope
 fun provideMoviePresenter(movieLoader: MovieLoader): Movie.Presenter {
 return MoviePresenter(view, movieLoader)
 }
 }
  • 24. Gains | Multiple classes per file // MoviesMvp.kt interface MoviesView { fun showMovies(movies: List<Movie>) } interface MoviesPresenter { fun loadMovies() }
  • 26. PAINS
  • 28. Pains | More methods trouble writing output: Too many field references: 131000; max is 65536. You may try using --multi-dex option.
  • 30. Pains | Crest of the wave moviesApi.loadMovies(genre)
 .map { it.movies }
  • 32. Pains | Abuse fun Context.checkSelfPermissionCompat(permission: String): Int {
 return ContextCompat.checkSelfPermission(this, permission)
 }
  • 33. TIPS
  • 34. Tips | Starting with Java works
  • 35. Tips | Avoid writing Kotlin as Java if (movieTitle == "Guardians of the galaxy") {
 movie.setGenre(comedy)
 } else if (movieRating > 4) {
 movie.setGenre(good)
 } else {
 movie.setGenre(others)
 } if (movie != null) {
 presenter.list(movie.getGenre())
 }
  • 36. Tips | Avoid writing Kotlin as Java movie.genre = when {
 movieTitle == "Guardians of the galaxy" -> comedy movieRating > 4 -> good else -> others
 } movie?.let {
 presenter.list(it.genre)
 }
  • 37. Tips | JVM annotations class MovieTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0): TextView(context, attrs, defStyleAttr) data class Movie(val title: String) : Parcelable { // ... companion object { @JvmField val CREATOR = object: Parcelable.Creator<Movie> { // ... } } }
  • 38. Tips | JVM annotations @file:JvmName(“ExtensionsUtils") companion object {
 @JvmStatic fun newInstance(tourCode: String): Fragment {
 // ...
 }
 }
  • 39. Tips | Adopt a code standard class MoviesPresenter(
 movies: List<Movie>,
 private val moviesApi: MoviesApi,
 override val view: Movies.View,
 router: Router,
 private val user: User,
 override val shareManager: ShareManager
 ): BaseMoviesPresenter(movies, router, user), Movies.Presenter { … }
  • 40. Tips | Adopt a code standard @file:JvmName(“ImageFormatUtil”) … ImageFormatUtil.isGif(file); vs @file:JvmName(“ImageFormatUtil”) … ImageFormatUtilKt.isGif(file);
  • 41. Tips | Adopt a code standard titleTextView.text = movie.title vs title_text_view.text = movie.title
  • 42. Tips | Adopt a code standard import kotlinx.android.synthetic.main.movie_activity.title_text_view as titleTextView
  • 43. Tips | Utils turn into extensions fun Date?.format(pattern: String): String {
 return this?.let { SimpleDateFormat(pattern, Locale.US).format(it) } ?: ""
 } public class DateUtils {
 public String format(Date date, String pattern) {
 if (date == null) {
 return "";
 }
 return new SimpleDateFormat(pattern, Locale.US).format(date);
 }
 }
  • 44. Tips | Watch out for nulls coming from Java val movie = Movie() // Classe Java 
 movie.genre = null
 movie.genre.toString() // NPE
  • 45. Tips | Null annotations // Java
 public static void prettyPrint(@NonNull String message) {
 System.out.print(message);
 }
 
 public @Nullable Rating getRating() { … } // Kotlin
 prettyPrint(null)
 val x: Rating = Test.getRating()
  • 46. Tips | Null annotations // Java
 public static void prettyPrint(@NonNull String message) {
 System.out.print(message);
 }
 
 public @Nullable Rating getRating() { … } // Kotlin
 prettyPrint("oi")
 val x: Rating? = Test.getRating()
  • 47. Tips | Null annotations @javax.annotation.ParametersAreNonnullByDefault package com.arctouch.movies;
  • 48. Tips | Named parameters val view = LayoutInflater.from(parent.context).inflate(
 resource = R.layout.listitem_diagram_showcase_category,
 root = parent,
 attachToRoot = false)
  • 49. Tips | Builders val movie = Movie(
 title = "Back to the Future 4",
 year = 2030,
 rating = 5f
 )
 
 val movie = Movie().apply {
 title = "Back to the Future 4"
 year = 2030
 rating = 5f
 }
  • 50. Tips | Interface default implementations // Kotlin interface MovieHandler { fun handleMovie() { print("default handling") } } // Java class JavaMovieHandler implements MovieHandler { }
  • 51. Tips | Annotation use-site target data class SomeDataClass(
 @field:SomeAnnotation
 @get:[Annotation1 Annotation2]
 @set:YetAnotherAnnotation
 @param:LastAnnotation
 var someProperty: SomeType, …
  • 52. Tips | Dagger MoviesComponent.java:38: error: io.reactivex.Observable<error.NonExistentClass> cannot be provided without an @Provides- or @Produces-annotated method.
  • 53. Tips | Java 8 lambda val map = mapOf("Java" to "Kotlin") map.forEach { key, value -> print("Java 8") } map.forEach { (key, value) -> print("Kotlin") }
  • 54. Tips | Kotlin Standard Library in Java goodMovies = CollectionsKt.minus(movies, badMovies); List<Movie> shortMovies = CollectionsKt.filter(movies, movie -> movie.length() > 100);
 shortMoviesTitles = CollectionsKt.map(shortMovies, Movie::getTitle);
  • 55. Tips | Unit leaking to Java // Kotlin
 val movieLoadedSubject: Subject<Unit> = PublishSubject.create<Unit>()
 
 movieLoadedSubject.subscribe {
 // no arg
 }
 // Java movieLoadedSubject.subscribe(unit -> {
 // can't ignore Unit arg :(
 });
  • 56. Tips | Less libs
  • 57. Tips | Less libs
  • 59. 5959
  • 64. 6464