Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Java to Kotlin

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

From Java to Kotlin

This talk covers why you would want to move from Java to Kotlin, and how you can do it in a safe and incremental way so that your team can get comfortable with it.

I also present a few examples.

Sample code is available here: https://github.com/dajulia3/java-to-kotlin-examples

Avatar for David Julia

David Julia

June 15, 2021
Tweet

More Decks by David Julia

Other Decks in Programming

Transcript

  1. Why Kotlin? • Concise • Safe (null safety) • Amazing

    Java interop • JDK 1.6+ compatible • Awesome IDE Support • More expressive type system • Gentle Learning curve • Soon to be the language of choice for gradle!
  2. “This reference is designed for you to easily learn Kotlin

    in a matter of hours.” -Kotlinlang.org docs
  3. Gentle Learning Curve • Can convert a code base piece

    by piece (good interop) • Slowly discover new features • Syntax is very approachable • Be productive immediately. • Learn the basics in a few hours
  4. How to start 1. Choose a project, add the kotlin

    plugin and std-lib to your build 2. Start converting dumb data classes to beautiful kotlin data objects 3. IntelliJ auto-convert to Kotlin 4. Extension functions 5. Beautiful null-checking syntax
  5. Concise: Data Classes • Java: 8 fields -> 105 lines,

    autogenerated by IDE ◦ And that’s not counting any builders! ◦ https://gist.github.com/dajulia3/7838b682b6c36a196a6e897 b7363376f • Kotlin: 8 fields -> 13 lines of Kotlin, no builders needed ◦ equals, hashCode, toString() by default
  6. Kotlin Data classes: They fit in presentation slides! data class

    Restaurant(val name: String, val ownerName: String, val headChefName: String, val cusineType: String, val shortDescription: String, val fullDescription: String, val websiteUrl: String, val rating: Int, val michelinStarRating: Int, val zagatRating: Int) { }
  7. Java Instantiation new Restaurant( "McDunwolds", "James McDunwold", "Ronald McDonald", "Fast

    Casual American", "Burgers, Fries, and Shakes.", "Burgers, Fries, and Shakes in a classy atmosphere.", "http://eatatmcdunwolds.com", 4, 98, 3 ) • Which name is the owner? • What do those ints mean? • I better make a builder… even more code to maintain/keep up-to-date
  8. Instantiation… No Builder Needed! Restaurant(name= "McDunwolds", ownerName = "James McDunwold",

    headChefName = "Ronald McDonald", cusineType = "Fast Casual American", shortDescription = "Burgers & Fries.", fullDescription = "Burgers, Fries, and Shakes in a classy atmosphere.", websiteUrl = "http://eatatmcdunwolds.com", rating = 4, zagatRating = 98, michelinStarRating = 3 ) • Named Arguments • No builder needed • No Java Compiler Hacks *cough*LOMBOK *cough*
  9. Immutable Jackson DTOs: Java version public class RestaurantDto{ private final

    String name; private final String headChefName; private final String cusineType; private final String shortDescription; private final String fullDescription; private final String websiteUrl; private final int rating; private final int michelinStarRating; private final int zagatRating; public RestaurantDto( @JsonProperty("name")String name, @JsonProperty("ownerName") String ownerName, @JsonProperty("headChefName") String headChefName, @JsonProperty("cusineType") String cusineType, @JsonProperty("shortDescription") String shortDescription, @JsonProperty("fullDescription") String fullDescription, @JsonProperty("websiteUrl") String websiteUrl, @JsonProperty("rating") int rating, @JsonProperty("michelinStarRating") int michelinStarRating, @JsonProperty("zagatRating") int zagatRating) { name = ownerName; this.headChefName = headChefName; this.cusineType = cusineType; this.shortDescription = shortDescription; this.fullDescription = fullDescription; this.websiteUrl = websiteUrl; //Continued on the next pane :) ... //….annnnd continuing where we left off this.rating = rating; this.michelinStarRating = michelinStarRating; this.zagatRating = zagatRating; } public String getHeadChefName() { return headChefName;} public String getCusineType() { return cusineType;} public String getShortDescription() { return shortDescription;} public String getFullDescription() { return fullDescription;} public String getWebsiteUrl() { return websiteUrl;} public int getRating() { return rating; } public int getMichelinStarRating() { return michelinStarRating;} public int getZagatRating() { return zagatRating;} }
  10. Immutable Jackson DTOs: Kotlin version data class RestaurantDto(val name: String,

    val ownerName: String, val headChefName: String, val cusineType: String, val shortDescription: String, val fullDescription: String, val websiteUrl: String, val rating: Int, val michelinStarRating: Int, val zagatRating: Int) { } //build.gradle compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.7.4" //Register it on your objectMapper val mapper = ObjectMapper().registerKotlinModule() 1 2 3
  11. Extension Functions fun ResultSet.getInstant(columnLabel: String): Instant { return this.getTimestamp(columnLabel).toInstant(); }

    fun whenDidItOccur(): Instant { return jdbcTemplate.queryForObject("SELECT * FROM incidents", { resultSet, i -> resultSet.getInstant("occurred_at") } ) }
  12. Null Checking Syntax Situation: We’re writing an app to help

    people deal with dairy intolerance. The API we’re hitting has incomplete information about recipes.
  13. Null Checking Syntax: The data model data class Recipe(val ingredients:

    List<Ingredient>, val chef: String ) data class Ingredient(val name: String, val category: IngredientCategory) enum class IngredientCategory { DRY_GOOD, DAIRY, NUT; fun significantAmount(): Boolean{ return true; } }
  14. Java Solution public boolean recipeContainsSignificantAmountOfDairy(int recipeId){ Recipe recipe = recipeClient.getRecipeById(recipeId);

    if(recipe != null ) { return recipe.getIngredients().stream().anyMatch(ingredient -> { if(ingredient.getCategory() == null) { return false; } return ingredient.getCategory().equals(IngredientCategory.DAIRY) && ingredient.getCategory().significantAmount(); }); } }
  15. Kotlin Solution fun recipeContainsSignificantAmountOfDairy(recipeId: Int): Boolean { val recipe =

    recipeClient.getRecipeById(recipeId) return recipe?.ingredients?.any { ingredient: Ingredient -> ingredient.category == IngredientCategory.DAIRY && ingredient.category.significantAmount() } ?: false }
  16. public boolean recipeContainsSignificantAmountOfDairy(int recipeId){ Recipe recipe = recipeClient.getRecipeById(recipeId); if(recipe !=

    null ) { return recipe.getIngredients().stream().anyMatch(ingredient -> { if(ingredient.getCategory() == null) { return false; } return ingredient.getCategory().equals(IngredientCategory.DAIRY) && ingredient.getCategory().significantAmount(); }); } } fun recipeContainsSignificantAmountOfDairy(recipeId: Int): Boolean { val recipe = recipeClient.getRecipeById(recipeId) return recipe?.ingredients?.any { ingredient: Ingredient -> ingredient.category == IngredientCategory.DAIRY && ingredient.category.significantAmount() } ?: false }
  17. Getting Started Tips/Resources • IntelliJ Kotlin Educational Plugin • http://try.kotlinlang.org/

    • Write in java, convert to kotlin, learn differences by going back and forth. • After converting to kotlin, leverage more features (e.g. “built-in” Kotlin optionals) • Just do it!