Java多类实现接口时重复方法的优化方案咨询
go2() Implementations in Java Interface Implementations Hey there! Let's tackle this redundancy problem step by step. First, let's clarify the code you're working with (I fixed a small access modifier issue since Java interface methods are implicitly public, so implementations need to declare @Override methods as public to compile correctly):
public interface I { void go1(); void go2(); } public class A implements I { @Override public void go1() { /* Custom logic for A */ } @Override public void go2() { /* Duplicated logic */ } } public class B implements I { @Override public void go1() { /* Custom logic for B */ } @Override public void go2() { /* Exact same duplicated logic as A */ } }
Now let's break down your options and find the best solution:
Option 1: Abstract Class with Shared go2() Implementation
This is a valid approach, but it comes with tradeoffs. Here's how it would look:
public abstract class BaseI implements I { @Override public void go2() { // Single source of truth for go2() logic } } public class A extends BaseI { @Override public void go1() { /* Custom logic for A */ } } public class B extends BaseI { @Override public void go1() { /* Custom logic for B */ } }
Pros: Eliminates redundancy entirely—subclasses inherit go2() automatically and only need to implement go1().
Cons: Java's single-inheritance rule becomes a limitation. If A or B ever needs to extend another class (not BaseI), you're stuck. This couples your implementation classes to the abstract class, reducing flexibility.
Option 2: Write go2() in Each Class and Call super()
This option doesn't make much sense in your current setup, and it's actually worse than your original problem.
First, without a common parent class, calling super.go2() would fail to compile—there's no superclass method to call. Even if you added a parent class, you'd still have to write go2() in every implementation class just to delegate to super(), which doesn't eliminate redundancy at all. This is a non-starter; skip this option entirely.
The Better Option: Use Interface Default Methods (Java 8+)
If you're using Java 8 or later, default methods in interfaces are the cleanest, most flexible solution. They let you define a default implementation for an interface method that all implementing classes inherit unless they choose to override it.
Here's how it works:
public interface I { void go1(); // Default implementation for go2() default void go2() { // Single, shared logic for go2() } } public class A implements I { @Override public void go1() { /* Custom logic for A */ } // No need to write go2()—uses the interface's default } public class B implements I { @Override public void go1() { /* Custom logic for B */ } // Same here—go2() is inherited automatically }
Pros:
- Zero redundancy: The shared
go2()logic lives in one place (the interface). - No inheritance limitations: Your implementation classes can still extend other classes while implementing
I. - Flexibility: If any class ever needs a custom
go2()implementation, it can simply override the default method without affecting others.
Honorable Mention: Composition (For Pre-Java 8 or High Flexibility)
If you're stuck on Java 7 or earlier, or you want even more decoupling, composition is a solid alternative. Extract the go2() logic into a separate helper class, then delegate to it from your implementation classes:
public class Go2Executor { public void runGo2() { // Shared go2() logic here } } public interface I { void go1(); void go2(); } public class A implements I { private final Go2Executor go2Executor = new Go2Executor(); @Override public void go1() { /* Custom logic for A */ } @Override public void go2() { go2Executor.runGo2(); } } public class B implements I { private final Go2Executor go2Executor = new Go2Executor(); @Override public void go1() { /* Custom logic for B */ } @Override public void go2() { go2Executor.runGo2(); } }
This avoids inheritance constraints, but it does require a small amount of boilerplate (the delegation line in each go2() method). It's great if you might need to swap out different go2() implementations later.
Final Recommendation
- If using Java 8+: Go with interface default methods—it's the simplest, most flexible solution with zero redundancy and no coupling.
- If stuck on Java 7 or earlier: Use the abstract class approach (Option 1) as the next best choice, or composition if you need to avoid inheritance limits.
- Avoid Option 2 entirely—it doesn't solve the redundancy problem and introduces unnecessary complexity.
内容的提问来源于stack exchange,提问作者Maaz Soan

