Source: https://web.stanford.edu/class/archive/cs/cs108/cs108.1082/handouts062/02AdvancedJavaTopics.pdf