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

From Java to Kotlin

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

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!