A quick recap and some "advanced" Java topics.



  • Jtools: jstack(threads), jstat(monitoring), jmap(memory)
  • transient keyword: not serialized when sent over the network
  • Field declaration in order of convention: access identifiers, then runtime behavior: transient (has to do with serialization), volatile. Static. Final. Annotations

  • Access identifiers aka visibility keywords
    • Private (within class incl. nested), default/package, protected (outside package too by subclasses), public.
      • Top level (non-nested) classes/interfaces can be public or package only! [1]
    • Note the usage of them in constructors eg: why use a private constructor?
      • A singleton
      • A utility class.
      • The constructor can only be accessed from static factory method inside the class itself
  • Method declaration: Access identifiers. Static. Final. Abstract. Synchronised. Native. Strictf. Annotations.
  • Operator precedence Static keyword: : For class attributes and methods. : Static fields are initialized when the class is first loaded: either referred or instantiated. : You can't access a nonstatic method or field from a static method(eg. main), because the static method doesn't have the instance. : Abstract static methods are not allowed (if you have 2 subclasses B and C, which of will get called with
  • Annotations Used by the compiler. creating object, casting, in implements, in throws. Can have 0, 1 or more elements.
  • varargs with
  • For-each loop: Applicable to arrays too! Cleaner code, especially for nested loops. But hides the iterator so you can't remove or replace elements as you traverse them -> wouldn't that cause a ConcurrentModification Exception anyways? You also can't use it to iterate multiple collections.
  • Iterable interface: Iterator itr = al.iterator(); while(itr.hasNext()) { Object element =; … }
  • Comparable interface: Total ordering (antisymmetry, transitivity, totality), throws if incompatible types
  • Collections: [ Concurrent Hashmap common mistake]

Interview setting

HR-friendly questions

What does the final keyword do?

From Ctci, I actually got asked this one from Evernote.

  • On classes: they can't be subclassed. (Offtopic: that both abstract and concrete classes can be subclassed.)
  • On methods: they can't be overiden.
  • On fields: they can't be modified once initialised.

finalize() on the other hand is the method called by the garbage collector before collecting the object.

What is the difference of interface vs abstract class?

  • Abstract classes vs interface:
    • Abstract class: Can be extended by a single class (single inheritance) but needs not to implement all abstract methods (as long as it's also an abstract - multiple layers), can have some implementation.
    • Interface: Can be implemented by many classes but must implement all methods (single layer), can hold no state or implementation (not engirely true on >Java8)
    • Both: neither can contain private methods

Override vs Overloading

Override (method from superclass) vs overloading (of arguments: change type and/or number of them)

Checked vs unchecked exceptions

Unchecked exceptions are all subclasses of RuntimeException. Checked are the rest and they need to be caught or declared with throws. : The consensus is that checked exceptions should be avoided because they break encapsulation: : If you change the low-level code so that it throws a new exception, the higher level classes must re-throw it until the one that handles it : A lot of classes need to be changed for something that happened in a different layer for which they don't need to care.

"How up to date are you?"

TODO: update this with Java 11 Java 9 features

  • Modules for dependency management (project jigsaw)
  • Jshell
    • HTTP2


Primitive types: byte, short: 16bits, int: 32bits, long: 64bit, float: 32 not accurate, double: 64bits not accurate, boolean, char: ' '

  • Unboxing (Object -> primitive) can result in NPE in runtime (autoboxing is the opposite): Under the hood the compiler converts the code
  • Ranges
    • Constants: Integer.MIN_VALUE,
  • Transformations:
    • Character to int: c-'0'
    • String.valueOf(123)

Data structures

Complements my datastructures introduction.


  • Initialization: new int[]{1, 2, 3} even 2d new int[][]{ {1,2}, {2,4} }
  • Classes Arrays and ArrayList
    • Arrays.sort: is in place, in acsending order, uses various algorithms depending on size of array
    • Arrays.binarySearch
    • ArrayList: dynamically resized (resizing cost), backed by an array, not thread safe. Good for iterating sequentially and getting elements.
      • ArrayList.add(i) moves all elements after i to the side
  • Transformations
    • Arrays.asList(new Integer[]{1,2,3})Collection.toArray()
      • Arrays.asList(new int[]) is not what you want probably!
    • String.toCharArray()new String(char[])
  • Copying
    • Arrays.copyOfRange(old, start, end) Careful the only things checked are start < 0, start > old.length, start > end (e.g. you can get a bigger array if end > old.length)
    • Using streams: IntStream.range(3,1).mapToObj(i->a[i]).toArray(Integer[]::new)


  • Immutable
  • Stringbuilder and StringBuffer (for thread safe)


  • LinkedList: double linked list, not thread safe. Good for inserting/deleting from the middle of the list.
  • Array (Integer[] not int!) to Collection Arrays.asList(new Integer[]{})
  • Instantiate and initialize: new ArrayList<>(){ { add(1) } }
  • Synchronized versions: Vector, StringBuffer, HashTable or ConcurrentHashMap, PriorityBlockingQueue


has head and tail: supports inserts/deletions from both ends. The semantics of the queue/stack (i.e. name of method used determine what is returned in each occasion.

  • Stack? push and pop (operate on the head)
  • Queue: add (works on the tail) and remove (on the head). Look for "// * Queue methods *" (or Stack) in the source ;-)


min heap by default, needs Comparable elements, add, peek, remove

  • HashSet uses HashMap behind the scenes. Supports a contains method in O(1). Use a HashSet if you don't need to associate a key to a value.
  • HashMap: complexity of all operations is actually O(1+n/m) where m is the number of "buckets", put/putIfAbsent and get/getOrDefault, Map.Entry : map.entrySet() to iterate
  • If order of insertion or access (e.g. LRU) matters use the Linked variants.



Where to use what

  • Common type? Abstract
  • Common behavior? Interface
  • Multiple inheritance is required? Interface
  • Need private or protected identifiers? Abstract


See dedicated post on concurrency


  • @FunctionalInterface annotation (interface with only one abstract method - excluding those inhereted by Object), useful for lambdas etc.

  • :: is a method reference. The method can be static or not.
  • Lambda body variants: a -> a.startsWith(" "), (a, b) -> System.out.println(a + b), (int a, int b) -> System.out.println(a + b),
a -> {
  // do something else
  return a';
  • intermediate vs terminal operations

Cheat sheet

Memory model

Java is pass by value: : for primitives this is self-proven : for objects: the reference is passed as a value. Therefore you can change inner objects that the argument contains but not the original object itself. A consequence is: : final List: allows modifying elements but compile-time error if modifying the List itself, Collections.unmodifiable offer truly immutable Lists.


  • Effective Java
  • CTci
  • EPI