Indie Hacker. Building Fifty.
I’ve encountered Java three times in my life.
First, in High School, where we approached Java as a fun tool to play with, without learning the theoretical fundamentals.
Second, when I studied Computer Science. We covered data structures, design patterns, OOP fundamentals, etc. I wasn’t interested in theory, so I studied just enough to pass.
3 Weeks Ago
I had a mental model of how Java worked — with some glaring gaps in my knowledge. In the past 3 weeks, while re-learning Java, I’ve made small tweaks to this model, which allowed me to think more deeply about advanced concepts in Java. Here follow the 6 gaps, and the tweaks I made to fix them.
1. Class vs Object
I’ve always used Object and Class interchangeably, which is not correct. I now understand that a class is a blueprint, and the object is what’s made from the blueprint. The Object is the thing that actually sits in memory. Once I made this small tweak, terms like defining a class and instantiating an object make a lot more sense. A nice parallel to this is the difference between a process and a program — where a program is a set of instructions, and a process is these instruction being executed.
2. Stack & Heap
Not understanding how, at a high level, data is organized in memory was a big gap. This made concepts like pass by reference and ideas related to polymorphism much harder to understand. I now define the stack as all the refs in scope that point to an object in the heap, and the heap as all the objects in memory. The best way is to actually just use a very high-level image representation:
3. Garbage Collector
The concept that the garbage collector determines which objects have no references to them, and then destroys those objects have always been foreign to me. Knowing this now allows me to think more deeply about memory management, and how to avoid Java’s version of memory leaks. In the past, I just took it for granted that something was cleaning up after me.
Static variables and methods tie state and behavior to a class, not an object.
This definition just “clicked” — and I find is the best way for me to think about the role of the static modifier in Java. Viewing static like this made concepts like a static init block easier to grasp, and why static members can’t access instance variables or methods — no instance variables are available when a class is first loaded.
Polymorphism means we can substitute one object for another as long as they are of the same type.
This definition and my new understanding of the stack & heap has allowed me to get a grip on the mechanism behind this pillar of OOP that has always seemed a bit abstract.
Person p = new Employee()
The reference (in the stack) is of type Person and points to the object of type Employee on the heap. This is the power of polymorphism — that a reference variable in the stack can point to an object on the heap, of a different type, as long as the object on the heap if a subtype of the reference on the stack.
Without this, tackling concepts like dependency injection, which is a core concept in Spring, would have been impossible.
I’m by no means an expert in Java. I’m still learning and have a long road ahead of me — but I’m confident that I have the basics covered.