OOP
Abstract classes vs interfaces, overloading vs overriding, inner classes, and the diamond problem.
12 questions
JuniorTheoryVery commonWhat are Java's four access modifiers, and what does each expose?
What are Java's four access modifiers, and what does each expose?
There are four levels. private limits a member to its declaring class; package-private (no keyword written) opens it to the same package; protected adds subclasses in any package; public opens it to everyone. Encapsulation means keeping fields private and exposing behaviour through methods, so a class can change its internals without breaking callers.
Common mistakes
- ✗Thinking a member with no modifier is
publicrather than package-private - ✗Believing
protectedexcludes same-package classes, when it actually includes them - ✗Calling a class encapsulated while every field has a matching public getter and setter
Follow-up questions
- →Why can a
protectedmember not be read from an arbitrary parent-typed reference in another package? - →How does a nested class reach the
privatefields of its enclosing class?
MiddleTheoryVery commonHow do an abstract class and an interface differ in Java?
How do an abstract class and an interface differ in Java?
An abstract class can hold instance state, constructors, and partly-implemented methods, but a class extends only one, so it models an "is-a" relationship. An interface is a pure contract a class can implement many of, modelling a "can-do" capability; since Java 8 it may carry default and static methods, yet its fields are constants and it has no constructor or per-instance state.
Common mistakes
- ✗Saying an interface can never have method bodies, forgetting
defaultandstaticmethods since Java 8 - ✗Believing a class can extend multiple abstract classes, when single inheritance permits only one
- ✗Thinking an interface holds per-instance state, when its fields are implicitly
public static finalconstants
Follow-up questions
- →Why did Java add
defaultmethods to interfaces, and what problem did they solve? - →When would you choose an abstract class over an interface for shared behaviour?
JuniorTheoryCommonWhat is a marker interface, and how is Serializable an example?
What is a marker interface, and how is Serializable an example?
A marker interface is an empty interface that declares no methods; implementing it simply tags a class with metadata. The JVM or a library then checks that type at runtime to decide behaviour. Serializable marks a class as safe to serialize, and Cloneable lets Object.clone() succeed. The class gains no methods — it only carries the tag.
Common mistakes
- ✗Expecting a marker interface to declare methods the class must implement, when by definition it is empty
- ✗Assuming
Serializableadds serialization logic rather than merely permitting the JVM to serialize the class - ✗Forgetting that a missing marker like
Cloneablemakes the relevant operation throw at runtime
Follow-up questions
- →How have annotations largely replaced marker interfaces in modern Java?
- →What happens at runtime if you call
clone()on a class that lacksCloneable?
JuniorTheoryCommonWhat is the difference between method overloading and overriding?
What is the difference between method overloading and overriding?
Overloading means several methods share one name but differ in parameter lists; the compiler picks one by argument types, so it is resolved at compile time. Overriding means a subclass redefines a superclass method with the same signature; the JVM picks the version by the object's actual runtime type, so it is resolved at runtime via dynamic dispatch.
Common mistakes
- ✗Believing a different return type alone is enough to overload a method when the parameter list is unchanged
- ✗Thinking overloading is resolved at runtime like overriding rather than fixed at compile time
- ✗Confusing which one needs an inheritance relationship — overriding does, overloading does not
Follow-up questions
- →Can a private or static method be overridden, and what happens if you try?
- →How does dynamic dispatch let an overridden method run despite the reference type?
JuniorTheoryCommonWhat does the super keyword do, and where can super(...) go?
What does the super keyword do, and where can super(...) go?
super references the immediate superclass from inside a subclass. super.method() calls the parent's version of an overridden method, and super.field reaches a hidden parent field. super(...) invokes a superclass constructor and must be the first statement in the subclass constructor; if omitted, the compiler inserts an implicit super() call to the no-arg parent constructor.
Common mistakes
- ✗Putting
super(...)after another statement, which fails to compile since it must come first - ✗Assuming the parent constructor is skipped entirely when no explicit
super(...)is written - ✗Thinking
supercan reach grandparents directly rather than only the immediate superclass
Follow-up questions
- →Why must
super(...)be the very first statement in a subclass constructor? - →How does
super.method()differ from a plain call when the method is overridden?
JuniorTheoryCommonWhat does the this keyword reference, and when is it needed?
What does the this keyword reference, and when is it needed?
this is a reference to the current object on which an instance method or constructor runs. Its common use is disambiguation: this.name = name distinguishes a field from a same-named parameter that shadows it. The this(...) form chains to another constructor of the same class for code reuse and, like super(...), must be the first statement in the constructor.
Common mistakes
- ✗Omitting
thiswhen a constructor parameter shadows a field, so the assignment silently writes to the parameter - ✗Trying to call
this(...)outside the first line of a constructor, which fails to compile - ✗Believing
thisis usable in a static context where no current object exists
Follow-up questions
- →What error occurs if both
this(...)andsuper(...)are written in one constructor? - →How does the compiler resolve a field versus a parameter when
thisis omitted?
MiddleTheoryCommonWhat kinds of nested class does Java have, and how do they differ?
What kinds of nested class does Java have, and how do they differ?
Java nests classes four ways. An inner (non-static) class holds an implicit reference to its enclosing instance, so it can read the outer object's members directly. A static nested class has no such link and behaves like a top-level class scoped inside another. A local class is declared inside a method, and an anonymous class is a one-shot inner class defined and instantiated in a single expression.
Common mistakes
- ✗Assuming a static nested class can access the outer instance's non-static fields, when it holds no outer reference
- ✗Forgetting that a non-static inner instance requires an existing outer instance to be created
- ✗Confusing an anonymous class with a named class, missing that it is defined and instantiated at once
Follow-up questions
- →How do you reach the outer
thisfrom inside an inner class when names collide? - →Why must variables captured by a local or anonymous class be effectively final?
MiddleTheoryCommonWhat do default, static and private methods in an interface do?
What do default, static and private methods in an interface do?
default gives an interface method a body that every implementer inherits and may override — that is how Java 8 could add methods to published interfaces without breaking them. static methods belong to the interface itself, are called as Iface.of(...), and are not inherited. private methods, added in Java 9, are helpers that share code between default and static bodies and stay invisible to implementers.
Common mistakes
- ✗Thinking a
defaultmethod can hold instance state — interface fields are stillpublic static finalconstants - ✗Expecting a
staticinterface method to be inherited and callable on an implementing class - ✗Assuming a
privateinterface method is visible to, or overridable by, implementers
Follow-up questions
- →What must a class do when it inherits two conflicting
defaultmethods from different interfaces? - →Why can a
defaultmethod not overrideequalsorhashCodeinherited fromObject?
MiddleTheoryOccasionalWhat is double-brace initialization, and why avoid it?
What is double-brace initialization, and why avoid it?
Double-brace initialization is new HashSet<>() {{ add("a"); }}: the outer braces create an anonymous subclass, and the inner braces are that subclass's instance-initializer block running the calls. It is an anti-pattern — it emits an extra class file, cannot extend final classes, and the anonymous instance holds an implicit this$0 reference to the enclosing object, which can leak memory.
Common mistakes
- ✗Thinking the doubled braces are special syntax rather than an anonymous subclass plus an initializer block
- ✗Believing it produces an immutable collection
- ✗Missing the implicit reference to the enclosing instance that causes leaks
Follow-up questions
- →Why does the anonymous instance keep a reference to the enclosing object?
- →What is a safer modern alternative for building a small populated collection?
SeniorTheoryOccasionalWhy is the marker interface Cloneable considered flawed in Java?
Why is the marker interface Cloneable considered flawed in Java?
Cloneable declares no clone() — it only tells Object.clone() not to throw, and Object.clone() is protected and native, so every class must re-declare a public clone() and call super.clone(). The copy it produces bypasses constructors, is shallow (mutable fields stay shared), and cannot assign final fields. A copy constructor or static factory is the recommended alternative.
Common mistakes
- ✗Believing
Cloneabledeclaresclone()— it declares no method at all - ✗Expecting
Object.clone()to deep-copy, when mutable fields stay shared with the original - ✗Forgetting that
clone()bypasses constructors, so invariants andfinalfields are never established
Follow-up questions
- →How does a copy constructor avoid the problems
Cloneablecreates? - →What must
clone()do by hand to deep-copy a class's mutable fields?
SeniorTheoryOccasionalWhat is the diamond problem, and how does Java avoid it?
What is the diamond problem, and how does Java avoid it?
The diamond problem is the ambiguity when one type inherits the same member along two paths and the compiler cannot tell which to use. Java forbids extending more than one class, so state inheritance stays unambiguous. It does allow multiple interfaces, and when two supply a clashing default method the class must override it and pick a version explicitly via Interface.super.method().
Common mistakes
- ✗Claiming Java allows multiple class inheritance, when only multiple interface implementation is permitted
- ✗Assuming a clashing
defaultmethod resolves automatically rather than forcing an explicit override - ✗Forgetting the
Interface.super.method()syntax needed to select one parent's default explicitly
Follow-up questions
- →Why does a
defaultmethod clash compile-fail while two abstract signatures merge cleanly? - →How would C++ handle the same diamond, and why did Java choose a different rule?
SeniorTheoryOccasionalCan private, static, and final methods be overridden in Java?
Can private, static, and final methods be overridden in Java?
No. A private method is invisible to subclasses, a final method is sealed against redefinition, and a static method belongs to the class, not an instance. A same-signature static method in a subclass does not override but hides the parent's: the call is resolved by the reference type at compile time, not the object's runtime type, so there is no polymorphism — unlike a true instance override.
Common mistakes
- ✗Calling a subclass
staticmethod an override, when it merely hides the parent's and skips polymorphism - ✗Expecting a hidden
staticmethod to dispatch by the object's runtime type rather than the reference type - ✗Thinking a
privatemethod participates in overriding, when subclasses cannot even see it
Follow-up questions
- →What does adding
@Overrideto a hiddenstaticmethod cause the compiler to do? - →How does method hiding interact with calling the method through a parent-typed reference?