Java Interfaces & Anonymous Classes
Tasks 1 – 6 with Complete Java Code
Task 1: Class Implementing Multiple Interfaces (UNION)
Verify that a class can implement multiple interfaces, and that abstract methods from all interfaces are taken as a
UNION — the implementing class must define all of them.
Code
interface Flyable {
void fly();
void land();
}
interface Swimmable {
void swim();
void dive();
}
interface Runnable {
void run();
}
// Class implements all 3 interfaces (UNION of abstract methods)
class Duck implements Flyable, Swimmable, Runnable {
public void fly() { [Link]("Duck is flying"); }
public void land() { [Link]("Duck is landing"); }
public void swim() { [Link]("Duck is swimming"); }
public void dive() { [Link]("Duck is diving"); }
public void run() { [Link]("Duck is running"); }
}
public class Task1 {
public static void main(String[] args) {
Duck d = new Duck();
[Link](); [Link](); [Link](); [Link](); [Link]();
}
}
Output
Duck is flying
Duck is landing
Duck is swimming
Duck is diving
Duck is running
Key point: Duck must implement fly(), land(), swim(), dive(), and run() — the full union of all three
interfaces.
Task 2: Default Methods in Interfaces
Create an interface with abstract methods and default methods. A class implementing it gets the default methods
for free and can optionally override them.
Code
interface MyInterface {
void abstractMethod1();
void abstractMethod2();
default void add() {
[Link]("Default add() from MyInterface");
}
default void display() {
[Link]("Default display() from MyInterface");
}
}
class MyClass implements MyInterface {
public void abstractMethod1() {
[Link]("abstractMethod1 implemented");
}
public void abstractMethod2() {
[Link]("abstractMethod2 implemented");
}
// default methods are inherited automatically
}
public class Task2 {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.abstractMethod1();
obj.abstractMethod2();
[Link](); // inherited default
[Link](); // inherited default
}
}
Output
abstractMethod1 implemented
abstractMethod2 implemented
Default add() from MyInterface
Default display() from MyInterface
Key point: Default methods (default void add(){}) are inherited by implementing classes without requiring
an override.
Task 3: Diamond Problem with Multiple Interface Inheritance
When two interfaces define a default method with the same signature and a class implements both, the compiler
forces the class to override the method — this is the Diamond Problem.
Code
interface A {
default void AB() {
[Link]("Default AB() from Interface A");
}
}
interface B {
default void AB() {
[Link]("Default AB() from Interface B");
}
}
// Diamond problem: C must OVERRIDE AB() to resolve ambiguity
class C implements A, B {
@Override
public void AB() {
[Link](); // calling A's version
[Link](); // calling B's version
[Link]("Resolved AB() in class C");
}
}
public class Task3 {
public static void main(String[] args) {
C obj = new C();
[Link]();
// Without overriding AB() in C, compiler throws an error
}
}
Output
Default AB() from Interface A
Default AB() from Interface B
Resolved AB() in class C
Key point: Without overriding AB() in class C, the compiler throws an error. Use [Link]() and
[Link]() to explicitly call each interface's version.
Task 4: Diamond Problem Does NOT Occur (Class + Interface)
When a class extends another class AND implements an interface that both define the same method, there is no
Diamond Problem — the class method always wins over the interface default.
Code
class A {
public void AB() {
[Link]("AB() from class A");
}
}
interface B {
default void AB() {
[Link]("Default AB() from Interface B");
}
}
// No diamond problem: class A's AB() takes priority over interface B's default
class C extends A implements B {
// No need to override -- class always wins over interface default
}
public class Task4 {
public static void main(String[] args) {
C obj = new C();
[Link](); // calls class A's AB(), not interface B's
}
}
Output
AB() from class A
Key point: Java's rule — a concrete class method always takes priority over an interface default method.
No ambiguity, no override required.
Task 5: Inheritance in Interfaces
Interfaces support inheritance via 'extends'. A child interface can override a parent interface's default method. A
class implementing the child interface gets the child's version.
Code
interface A {
void M1();
void M2();
void M3();
default void greet() {
[Link]("Hello from Interface A (default greet)");
}
}
// Child interface B extends A and OVERRIDES the default method
interface B extends A {
@Override
default void greet() {
[Link]("Hello from Interface B (overridden greet)");
}
}
// Class C implements B -- gets B's version of greet()
class C implements B {
public void M1() { [Link]("M1 implemented in C"); }
public void M2() { [Link]("M2 implemented in C"); }
public void M3() { [Link]("M3 implemented in C"); }
}
public class Task5 {
public static void main(String[] args) {
C obj = new C();
obj.M1(); obj.M2(); obj.M3();
[Link](); // gets B's overridden version
}
}
Output
M1 implemented in C
M2 implemented in C
M3 implemented in C
Hello from Interface B (overridden greet)
Key point: Yes — a child interface CAN override a parent interface's default method. Class C, which
implements B, gets B's overridden version of greet().
Task 6: Anonymous Class Implementation
An anonymous class is a class defined and instantiated in a single expression — useful for one-time
implementations without creating a named class.
Rules for anonymous classes:
1. Can implement exactly ONE interface directly
2. Can extend exactly ONE class
3. Can override default methods inline
4. Cannot implement multiple interfaces directly — use a combining interface as a workaround
Code
interface Animal {
void sound();
default void breathe() {
[Link]("Animal breathes");
}
}
interface Vehicle {
void move();
}
// Helper interface combining both (needed for anonymous multi-interface)
interface FlyingCar extends Animal, Vehicle {}
public class Task6 {
public static void main(String[] args) {
// 1. Basic anonymous class implementing an interface
Animal dog = new Animal() {
public void sound() {
[Link]("[Anon] Dog barks");
}
};
[Link]();
[Link](); // uses default method
// 2. Anonymous class OVERRIDING the default method
Animal cat = new Animal() {
public void sound() {
[Link]("[Anon] Cat meows");
}
@Override
public void breathe() {
[Link]("[Anon] Cat breathes quietly");
}
};
[Link]();
[Link](); // overridden version
// 3. Anonymous class via combined interface (multi-interface workaround)
FlyingCar fc = new FlyingCar() {
public void sound() {
[Link]("[Anon FlyingCar] Vroom-woof!");
}
public void move() {
[Link]("[Anon FlyingCar] Flying through traffic");
}
};
[Link]();
[Link]();
[Link](); // inherited default from Animal
// 4. Anonymous class extending a concrete class
Animal anonExtend = new Animal() {
public void sound() {
[Link]("[Anon] Unknown animal sound");
}
};
[Link]();
// NOTE: Cannot do: new Animal(), Vehicle() { ... } -- compile error!
// Anonymous classes can implement only ONE interface directly.
}
}
Output
[Anon] Dog barks
Animal breathes
[Anon] Cat meows
[Anon] Cat breathes quietly
[Anon FlyingCar] Vroom-woof!
[Anon FlyingCar] Flying through traffic
Animal breathes
[Anon] Unknown animal sound
Key point: Anonymous classes are ideal for short, one-off implementations. For multi-interface scenarios,
create a combining interface that extends both.