issues masquerading as IllegalArgumentException class BankAccount { BankAccount(String identifier) { if (identifier == null) throw new IllegalArgumentException(“missing identifier”); } }
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
Java if (employee.getAge() == supervisor.getAge()) // Java int employeeAge = employee.getAge(); int supervisorAge = supervisor.getAge(); if (employeeAge == supervisorAge) ... ...similarly for all 8 primitive types
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
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))
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) !!!
To Implement hashCode when overriding equals • 22. Poor implementation leading to collisions/scalability/security problems • 23. Inconsistent equals and hashCode 22
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()); }
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
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 }
be acquired and released in the correct order to avoid deadlocks // Kotlin Locks.usingLockA { ... usingLockB { //not accessible from outside the scope of LockA ... } ... }
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
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 }
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