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

Kotlin prevents over 50 types of Java defects

Dan Rusu
October 22, 2018

Kotlin prevents over 50 types of Java defects

This demonstrates over 50 types of Java defects which Kotlin can prevent

Dan Rusu

October 22, 2018
Tweet

More Decks by Dan Rusu

Other Decks in Programming

Transcript

  1. Kotlin Prevents Over 50 Types of Java Bugs Dan R

    u su Ky le Platt O c t 1 7 , 2 0 1 8
  2. FR 4 1. Invalidating Implicit Contracts Initial Refactored void entryPoint(List<String>

    info) { if (info == null) throw new IllegalArgumentException(); doSomeInnerLogic(info); } void doInnerLogic(List<String> passedInfo) { log(passedInfo.size()) // never null ... } void initialEntryPoint(List<String> info) { if (info == null && isValid()) //Changed throw new IllegalArgumentException(); doSomeInnerLogic(info); } void doInnerLogic(List<String> passedInfo) { log(passedInfo.size()) // oops null ... }
  3. FR 5 2. Clearing Data With Null //Java Map<Product, Quantity>

    inventory; ... Integer newQuantity = null; try { newQuantity = loadQuantity() - 1; } catch (Exception e) { log(e); } inventory.put(product, newQuantity); //Quantity accidentally cleared
  4. 6 3. Autoboxing/Unboxing //Java - this will throw a null

    pointer exception public boolean makesOverAMillionDollars(String name) { Map<String, Long> salaries = getSalaries(); long salary = salaries.get(name); … }
  5. FR Misinterpreting Null • 4. Null Boolean as false •

    5. Null String as empty • 6. Null Integer as 0 • i.e. ResultSet 7 //Java if (Boolean.TRUE.equals(isSuspiciousAction)) return reportToAuthorities;
  6. 8 7. Passing Null When Not Expected //Java – null

    issues masquerading as IllegalArgumentException class BankAccount { BankAccount(String identifier) { if (identifier == null) throw new IllegalArgumentException(“missing identifier”); } }
  7. FR 8. Changing Method Return Types 10 // Java //

    getAge() returned an int so this check was correct but // was later changed to return Integer if (brother.getAge() == sister.getAge()) // potential twins //...similarly for all 8 primitive types
  8. FR 11 9. Inlining Code With Autoboxing Initial Refactored //

    Java if (employee.getAge() == supervisor.getAge()) // Java int employeeAge = employee.getAge(); int supervisorAge = supervisor.getAge(); if (employeeAge == supervisorAge) ... ...similarly for all 8 primitive types
  9. 12 10. Object Caching // Java Integer first = 100;

    Integer second = 100; // Condition passes since these values use the Integer cache if (first == second) ... Integer third = 200; Integer fourth = 200; // Oops, condition fails since 200 is out of range of Integer cache if (third == fourth) factory pattern can cause similar caching problems with any class
  10. FR 11. Checking Referential Equality When You Didn’t Intend To

    13 // Java if (firstName == lastName) ...
  11. FR 15 Accidental Assignments • 12. Boolean assignment // Java

    boolean isEmployed = loadEmploymentStatus(person); // Incorrect check due to assignment if (isEmployed = person.isMarried()) // Employed and married or unemployed and single ... if (isEmployed) // this variable was accidentally modified • 13. Variable assignment of any type // Java // Attempt to determine twins based on age boolean singleSetOfTwins = ((age1 = age2) != (age3 = age4))
  12. FR 17 Switch Defects • 14. Forgetting a Case •

    15. Adding new Enum values, forgetting to update usages • 16. Missing break // Java switch (priority) { case LOW: priorityColor = Color.GREEN; // Oops, forgot break case MEDIUM: ... } // Kotlin val priorityColor = when (priority) { LOW -> Color.GREEN MEDIUM, HIGH -> Color.YELLOW CRITICAL -> Color.RED }
  13. 19 • 17. Backwards Ternary int age = person ==

    null ? person.age : 0; • 18. Nested ternaries often misinterpreted int spouseAge = person == null ? 0 : person.spouse == null ? person.spouse.age : 0; Ternary Defects
  14. 21 19. Non-Final Classes and InstanceOf class Person { private

    String name; ... public boolean equals(Object other) { return other instanceof Person && ((Person) other).name.equals(name); } } class Manager extends Person { int numSubordinates; ... public boolean equals(Object other) { if (!super.equals(other)) return false; return other instanceof Manager && ((Manager) other).numSubordinates == numSubordinates; } } person.equals(manager) should imply manager.equals(person) !!!
  15. FR Implementing HashCode • 20. Logic Mistakes • 21. Forgetting

    To Implement hashCode when overriding equals • 22. Poor implementation leading to collisions/scalability/security problems • 23. Inconsistent equals and hashCode 22
  16. 23 • 24. Missing nullability annotations or Not guarding against

    null • 25. Forgetting To Update Methods • 26. Invalid equals implementation And More…
  17. FR Accidental Overrides 25 • 27. Accidentally override superclass method

    by adding a method to subclass • 28. Add method to superclass without realising subclass has a method with the same signature
  18. 26 • 29. Changing SuperClass method signature • 30. Changing

    subclass method signature • 31. Incorrect spelling, capitalization of method name Breaking Overrides
  19. FR 32. Class Cast Exceptions With Raw Types 28 //Java

    List things = new ArrayList(); things.add(new Person()); Dog dog = (Dog)things.get(0);
  20. FR 29 33. Raw Type Heap Pollution // Java List<String>

    names = new ArrayList<>(); updateList(names); // Heap pollution: The list of Strings now contains a Date! ... void updateList(List elements) { //raw List type elements.add(new Date()); }
  21. FR 30 34. Unchecked Casts // Java List<Integer> numbers =

    new ArrayList<>(); Date nastyValue = new Date(); numbers.add(Utils.<Integer>convert(nastyValue)); // Heap pollution: The list of Integers now contains a Date! ... // In Utils.java static <T> T convert(Object value) { return (T)value; // unchecked cast causes heap pollution } Kotlin prevents this when using reified generics
  22. 31 35. Covariant Arrays // Java // class Animal, class

    Dog extends Animal, class Cat extends Animal Dog[] dogs = {new Dog("Woofy"), new Dog("Fluffy")}; updateAnimals(dogs); ... void updateAnimals(Animal[] animals) { animals[0] = new Cat(); // This will throw a runtime exception }
  23. FR Lazy Initialization Defects • 36. Non-Thread Safe Lazy Initialization

    • 37. Forgetting or incorrect Double Checked locking Kotlin prevents this with • By lazy delegate • Singleton pattern is built into the language 33
  24. FR 36 39. Pattern Enforcement • Eg. Forcing locks to

    be acquired and released in the correct order to avoid deadlocks // Kotlin Locks.usingLockA { ... usingLockB { //not accessible from outside the scope of LockA ... } ... }
  25. 38 40. Missing Types // Kotlin fun eval(expr: Expr): Double

    = when(expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN }
  26. FR Locking Down Inheritance Tree • 41. Locking down inheritance

    tree • Package protected is not secure in Java • 42. Sealed Classes enable pattern matching • More robust • Less error prone 39
  27. 41 • 43. Off By One for (i in 1..10)

    • 44. Index out of bounds • forEach – java doesn’t allow checked exceptions in lambdas • forEachIndexed Array Indices
  28. FR 45. Extending Classes • Extending classes that were never

    designed to be extended • Forgetting final • “Design classes and methods for inheritance or declare them final [6]. Left non-final, a class or method can be maliciously overridden by an attacker” - Java Secure Coding Guidelines 42
  29. FR 43 46. Initialize And Cleanup Pattern • Kotlin allows

    you to extract more reusable patterns than Java // Kotlin writeLock.lock() //update balance writeLock.release() //missing finally writeLock.withLock { //update balance, can throw checked exceptions }
  30. 44 • 47. String templates make it easy to spot

    missing spaces "Hello my name is$name" • 48. Triple quoted strings prevent incorrect escape sequences path = """c:\program files\alpaca.exe""" Strings
  31. FR 46 Method Parameters • 50. Mutating parameters leads to

    surprise defects • 51. Named parameters avoid invalid argument order // Kotlin Rectangle(20, 30) Rectangle(width = 20, height = 30)
  32. 48 • Prevent incorrect units • Doesn’t sacrifice scalability •

    Zero cost abstraction, no memory overhead • Famous NASA example computeSpeed(200.miles(), 2.hours()) // Mismatch, Does not compile fun computeSpeed(distance: Kilometers, time: Hours) : Speed 52. Inline Classes