Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dear Kotliners - Java Developers are Humans too

This talk is to help the kotliners understand the caveats of the default interoperability features provided by Kotlin and provides a few tips for interoperability to make Java developers life easier.

  • Be the first to comment

Dear Kotliners - Java Developers are Humans too

  1. 1. Dear otliners Java Developers are Humans Too @Vivek_Chanddru
  2. 2. Quick Check
  3. 3. A Kotlin Enthusiast Rooting for Java Developers
  4. 4. Why is there so much hype? • Unveiled on July, 2011 by JetBrains and released Feb, 2016 • Received First Class support at Google I/O 2017 • A much better Java • Provides support similar to other modern languages • A boon for Java programmers writing verbose code
  5. 5. Kotlin Adoption
  6. 6. Kotlin Adoption
  7. 7. Kotlin Adoption We are here now
  8. 8. Kotlin Adoption • Very soon, Kotlin is going to overtake Java (For Android) • Libraries are popping up with Kotlin support • New libraries are developed using Kotlin • Sample apps and code are in Kotlin • Medium is filled with wonders of Kotlin
  9. 9. Kotlin is growing and people are Adopting it So Why Bother about Java Developers?
  10. 10. Problems in Adopting Kotlin • Have to learn an all new language 😫 • Team members not willing to learn a new language • Company is not willing to spend time and money on R&D • Fear of breaking what is already working fine • Hard to find Kotlin experts to get the work done
  11. 11. Most of it is not their fault! A lot of factors come into play that stops their adoption
  12. 12. What goes on in a Java developer's mind? • The world is moving on leaving them behind • See a new blog? It is in Kotlin • An awesome library that they want? It is developed and optimized for Kotlin • Left with the default implementation of Kotlin interoperability support
  13. 13. You can support them! With very minimal work on your side
  14. 14. How Kotlin helps with interoperability • Kotlin works out of box with Java (mostly) • Java classes and methods can be used directly from Kotlin • Kotlin classes and functions can be used from Java • With very little effort, you can make Java developers’ life much easier and write better looking code
  15. 15. Tips for Interoperability The typical Do's and Don'ts
  16. 16. Think about access scopes What you think is invisible is available in plain sight! 1
  17. 17. Visibility Modifiers - Kotlin • Private fields in Kotlin stay private in Java • Private top-level declarations turns out to be package-local declarations • Protected members in Java are accessible to other classes in same package • Internal members become public after some name-mangling • Public stay public
  18. 18. Be mindful of the class name Name the class to make more sense 2
  19. 19. fun calculateAge(dob: Date): Int { //some magic happens here return 42 } Kotlin - AmazingUtils.kt
  20. 20. fun calculateAge(dob: Date): Int { //some magic happens here return 42 } void runAgeDemo(Date date) { AmazingUtilsKt
 .calculateAge(date); } Kotlin - AmazingUtils.kt Java
  21. 21. @file:JvmName("Utils") fun calculateAge(dob: Date): Int { //some magic happens here return 42 } Kotlin - AmazingUtils.kt
  22. 22. Utils.calculateAge(date); void runAgeDemo(Date date) { } @file:JvmName("Utils") fun calculateAge(dob: Date): Int { //some magic happens here return 42 } Kotlin - AmazingUtils.kt Java
  23. 23. @file:JvmName(“Utils") @file:JvmMultifileClass fun calculateAge(dob: Date): Int { //some magic happens here return 42 } @file:JvmName("Utils")
 @file:JvmMultifileClass fun isEligibleToVote(age: Int): Boolean { //some magic happens here return age >= 18 }
 A.kt B.kt
  24. 24. void runAgeDemo(Date date) { int age = Utils.calculateAge(date); boolean isEligible = Utils.isEligibleToVote(age); } Java
  25. 25. Have fun() with names Name the methods to make more sense 3
  26. 26. fun String?.isNullorEmpty(): Boolean { return this != null && this.isEmpty() } Kotlin
  27. 27. Does not show the receiver type. Might want function name to give more context fun String?.isNullorEmpty(): Boolean { return this != null && this.isEmpty() } Kotlin void nullOrEmptyDemo(String s) { boolean nullorEmpty = Utils.isNullorEmpty(s); } Java
  28. 28. @file:JvmName("Utils")
 @JvmName("isStringNullorEmpty") fun String?.isNullorEmpty(): Boolean { return this != null && this.isEmpty() } Kotlin
  29. 29. @file:JvmName("Utils")
 @JvmName("isStringNullorEmpty") fun String?.isNullorEmpty(): Boolean { return this != null && this.isEmpty() } Gives more context on what the method is and what it does. Kotlin void nullOrEmptyDemo(String s) { boolean nullorEmpty = Utils.isStringNullorEmpty(s); } Java
  30. 30. Rename the Accessors Name the getters and setters the way you want 4
  31. 31. class Person { var name: String? = null var age: Int? = null } Kotlin
  32. 32. void personDemo(Person person) { person.getName(); person.getAge(); person.setName("Vivek"); } class Person { var name: String? = null var age: Int? = null } Java Kotlin
  33. 33. var name: String? = null @JvmName("getPersonName") get() { return field?.toLowerCase() } set(value) { field = value?.toUpperCase() } var age: Int? = null class Person { } Kotlin
  34. 34. class Person { var name: String? = null @JvmName("getPersonName") get() { return field?.toLowerCase() } set(value) { field = value?.toUpperCase() } @get:JvmName("getpersonAge") @set:JvmName("setPersonAge") var age: Int? = null
 } Kotlin
  35. 35. void personDemo(Person person) { person.getPersonName(); person.getpersonAge(); person.setName("Vivek"); } class Person { var name: String? = null @JvmName("getPersonName") get() { return field?.toLowerCase() } set(value) { field = value?.toUpperCase() } @get:JvmName("getpersonAge") @set:JvmName("setPersonAge") var age: Int? = null
 } Java Kotlin
  36. 36. Never forget your Companions Companion functions need a little tweak to look nice 5
  37. 37. class AmazingClass { companion object { fun simpleUtilFunction() { //Do some magic here } } } Kotlin
  38. 38. void companionDemo() { AmazingClass
 .Companion
 .simpleUtilFunction(); } class AmazingClass { companion object { fun simpleUtilFunction() { //Do some magic here } } } Kotlin Java
  39. 39. class AmazingClass { companion object { fun simpleUtilFunction() { //Do some magic here } } } @JvmStatic Kotlin
  40. 40. void companionDemo() { AmazingClass.simpleUtilFunction(); } class AmazingClass { companion object { fun simpleUtilFunction() { //Do some magic here } } } @JvmStatic Kotlin Java
  41. 41. Call properties by their names There is no need of an accessor for everything 6
  42. 42. Accessing Properties by Name • There are three scenarios where the properties of a class can be accessed directly without getters and setters from Java • When the property is a `const` • When the property is a `lateinit` • When the property is annotated with `@JvmField`
  43. 43. class AmazingClass { companion object { const val BASE_URL_GOOGLE 
 = "www.google.com" val BASE_URL = "www.droidcon.at" } } Kotlin
  44. 44. void companionDemo() { system.out.println(AmazingClass.BASE_URL_GOOGLE);
 system.out.println(AmazingClass.Companion.getBASE_URL() );
 } class AmazingClass { companion object { const val BASE_URL_GOOGLE 
 = "www.google.com" val BASE_URL = "www.droidcon.at" } } Kotlin Java
  45. 45. void companionDemo() { system.out.println(AmazingClass.BASE_URL_GOOGLE);
 system.out.println(AmazingClass.Companion.getBASE_URL() );
 } class AmazingClass { companion object { const val BASE_URL_GOOGLE 
 = "www.google.com" val BASE_URL = "www.droidcon.at" } } Kotlin Java
  46. 46. class AmazingClass { companion object { const val BASE_URL_GOOGLE 
 = "www.google.com" 
 val BASE_URL = "www.droidcon.at" } } @JvmField Kotlin
  47. 47. void companionDemo() { system.out.println(AmazingClass.BASE_URL_GOOGLE);
 system.out.println(AmazingClass.BASE_URL); );
 } class AmazingClass { companion object { const val BASE_URL_GOOGLE 
 = "www.google.com" 
 val BASE_URL = "www.droidcon.at" } } @JvmField Kotlin Java
  48. 48. 
 class LazyClass {
 lateinit var mandatoryVariable: String 
 var optionalVariable: String? = null
 } Kotlin
  49. 49. Java
 void propertyAccessDemo() { LazyClass lazyClass = new LazyClass(); lazyClass.mandatoryVariable = "abcd"; lazyClass.setMandatoryVariable("vivek"); } 
 class LazyClass {
 lateinit var mandatoryVariable: String 
 var optionalVariable: String? = null
 } Kotlin
  50. 50. Java
 void propertyAccessDemo() { LazyClass lazyClass = new LazyClass(); lazyClass.optionalVariable = "hello"; //not available } 
 class LazyClass {
 lateinit var mandatoryVariable: String 
 var optionalVariable: String? = null
 } Kotlin
  51. 51. fun() with defaults Functions with default params are not straight-forward 7
  52. 52. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin
  53. 53. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin void increaseValueDemo() { DemoKt.increaseValue(60,1); } Java
  54. 54. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin void increaseValueDemo() { DemoKt.increaseValue(60,1); } Java DemoKt.increaseValue(60); This is an error. No methods match such signature
  55. 55. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin @JvmOverloads
  56. 56. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin @JvmOverloads
  57. 57. fun increaseValue( givenValue: Int,
 increaseBy: Int = 1): Int { return givenValue + increaseBy } Kotlin @JvmOverloads void intelligentMethodDemo() { DemoKt.increaseValue(60,5); DemoKt.increaseValue(60); } Java
  58. 58. Handle with care Exceptions are your worst enemies! Never forget them! 8
  59. 59. fun writeBytes(bytes: ByteArray) { val file = File(“file_path") val fos = FileOutputStream(file) fos.write(bytes) fos.close() } Kotlin This line is going to throw 
 an exception
  60. 60. fun writeBytes(bytes: ByteArray) { val file = File(“file_path") val fos = FileOutputStream(file) fos.write(bytes) fos.close() } Kotlin void exceptionDemo() { byte[] bytes = new byte[]; DemoKt.writeBytes(bytes); } Java Does not throw any compile time errors. Silently crashes at Runtime
  61. 61. fun writeBytes(bytes: ByteArray) { val file = File(“file_path") val fos = FileOutputStream(file) fos.write(bytes) fos.close() } Kotlin @Throws(IOException::class) Document the exceptions that might be thrown
  62. 62. fun writeBytes(bytes: ByteArray) { val file = File(“file_path") val fos = FileOutputStream(file) fos.write(bytes) fos.close() } Kotlin @Throws(IOException::class) void exceptionDemo() { byte[] bytes = new byte[]; DemoKt.writeBytes(bytes); } Java Shows a compile time error and provides an option to surround with try catch block
  63. 63. Working with Function Types Function types which return Unit might not be what you want 9
  64. 64. The pitfalls of Function Types • Fan of higher order functions and lambdas? • Kotlin higher-order functions are a very nice feature to use but should be used carefully. • If your function type returns `Unit`, then, when used from Java, it has to return `Unit.INSTANCE` which is unidiomatic • Alternatives are to use a SAM (Single Abstract Method) interface in Java or Kotlin • This issue will soon be fixed in one of the Kotlin releases and until then, you can use Function Types bearing in mind the inconveniences caused to Java consumers
  65. 65. fun lambdaExample(block: (Int) -> Unit) { //do some magic block(3) } Kotlin
  66. 66. fun lambdaExample(block: (Int) -> Unit) { //do some magic block(3) } Kotlin DemoKt.lambdaExample(integer -> { system.out.println(integer); return Unit.INSTANCE; }); DemoKt.lambdaExample(integer -> { system.out.println(integer); return null; }); Java
  67. 67. interface Callback { fun doSomething(value: Int) } fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } Kotlin We have a SAM interface written in Kotlin
  68. 68. Java
 void lambdaDemo() { DemoKt.lambdaExampleInterface( integer -> { system.out.println(integer); }); } interface Callback { fun doSomething(value: Int) } fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } Kotlin
  69. 69. interface Callback { fun doSomething(value: Int) } fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } Kotlin Kotlin
 lambdaExampleInterface(object : Callback { override fun doSomething(value: Int) { //do something here } })
  70. 70. Java
 interface Callback { void doSomething(int value) } Kotlin
 fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } We have a SAM interface written in Java
  71. 71. Java
 interface Callback { void doSomething(int value) } Kotlin
 fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } Java
 void lambdaDemo() { DemoKt.lambdaExampleInterface( integer -> { system.out.println(integer); }); }
  72. 72. Java
 interface Callback { void doSomething(int value) } Kotlin
 fun lambdaExampleInterface( callback: Callback) { callback.doSomething(3) } Kotlin
 lamdaExampleInterface(Callback { it -> //do something here })
  73. 73. Exposing immutable collections Java does not treat collections as immutable. 10
  74. 74. Collections - Handle with Care • In Kotlin, collections are by default immutable (list, set, map etc) • Meaning, you cannot add or modify values in the collection • If a mutable version is required, the request should be explicit to create a mutable version of the collection • When exposing immutable collections through public APIs, Java consumers can receive them and make changes to it, causing inconsistency
  75. 75. fun getPersonList(): List<Person> { val personList: List<Person> = fetchPersonList() return personList } Kotlin
  76. 76. fun getPersonList(): List<Person> { val personList: List<Person> = fetchPersonList() return personList } Kotlin void collectionDemo() { DemoKt.getPersonList().add( new Person("Vivek",30)); } Java
  77. 77. fun getCurrentPersonList(): List<Person> { val personList = getPersonList() val currentPersonList = mutableListOf<Person>() Collections.copy( currentPersonList ,personList) return currentPersonList } Kotlin
  78. 78. fun getCurrentPersonList(): List<Person> { val personList = getPersonList() val currentPersonList = mutableListOf<Person>() Collections.copy( currentPersonList ,personList) return currentPersonList } Kotlin void collectionDemo() { DemoKt.getCurrentPersonList().add( new Person("Vivek",30)); } Java
  79. 79. Thank you! Start shooting your questions my way

    Be the first to comment

    Login to see the comments

  • sdhar27

    Sep. 22, 2018

This talk is to help the kotliners understand the caveats of the default interoperability features provided by Kotlin and provides a few tips for interoperability to make Java developers life easier.

Views

Total views

254

On Slideshare

0

From embeds

0

Number of embeds

5

Actions

Downloads

7

Shares

0

Comments

0

Likes

1

×