Skip to content

接口私有方法

写过 JDK 8 的默认方法吗?一定遇到过这个问题:

几个默认方法里有重复逻辑,想提取成私有方法,但接口里不能定义 private 方法。

到了 JDK 9,这个限制解除了。

解决的问题

在 JDK 8 中,默认方法里如果有重复代码,你只能:

java
// JDK 8:没法提取公共私有方法
public interface Logger {
    default void logInfo(String message) {
        // 公共逻辑
        String formatted = "INFO: " + format(message);
        System.out.println(formatted);
        logToFile(formatted);
    }
    
    default void logError(String message) {
        // 同样的公共逻辑
        String formatted = "ERROR: " + format(message);
        System.out.println(formatted);
        logToFile(formatted);
    }
    
    // ❌ 报错:Interface cannot have private methods
    // private String format(String message) {
    //     return "[" + LocalDateTime.now() + "] " + message;
    // }
}

结果:要么代码重复,要么把公共逻辑抽取到一个独立的工具类里。

JDK 9 的方案

JDK 9 允许接口定义 private 方法:

java
public interface Logger {
    default void logInfo(String message) {
        String formatted = format("INFO", message);
        save(formatted);
    }
    
    default void logError(String message) {
        String formatted = format("ERROR", message);
        save(formatted);
    }
    
    // ✅ JDK 9+:私有方法
    private String format(String level, String message) {
        return "[" + level + "] " + LocalDateTime.now() + ": " + message;
    }
    
    // ✅ 私有静态方法也可以
    private static void save(String message) {
        // 保存到日志文件
        System.out.println("Saving: " + message);
    }
}

完整示例

java
public class LoggerDemo {

    interface Logger {
        default void info(String message) {
            log("INFO", message);
        }
        
        default void warn(String message) {
            log("WARN", message);
        }
        
        default void error(String message) {
            log("ERROR", message);
        }
        
        default void error(String message, Throwable t) {
            log("ERROR", message + " - " + t.getMessage());
        }
        
        // 私有方法:公共格式化逻辑
        private String log(String level, String message) {
            String formatted = format(level, message);
            print(formatted);
            return formatted;
        }
        
        // 私有静态方法
        private static String format(String level, String message) {
            return String.format("[%s] %s - %s",
                LocalDateTime.now(),
                level,
                message
            );
        }
        
        // 私有静态方法:打印到不同目的地
        private static void print(String message) {
            System.out.println(message);
            // 实际场景可能是写入文件、发送到日志服务器等
        }
    }
    
    // 使用默认实现
    static class SimpleLogger implements Logger {}
    
    public static void main(String[] args) {
        Logger logger = new SimpleLogger();
        
        logger.info("应用启动");
        logger.warn("内存使用率 80%");
        logger.error("连接数据库失败");
        logger.error("处理请求异常", new RuntimeException("timeout"));
    }
}

私有方法的规则

可以是实例方法

java
interface Calculator {
    // 私有实例方法
    private int compute(int x) {
        return x * x + 2 * x + 1;  // x² + 2x + 1
    }
    
    default int evaluate(int x) {
        return compute(x);
    }
}

可以是静态方法

java
interface StringUtils {
    // 私有静态方法
    private static boolean isBlank(String s) {
        return s == null || s.trim().isEmpty();
    }
    
    static String process(String input) {
        if (isBlank(input)) {
            return "N/A";
        }
        return input.toUpperCase();
    }
}

不能被继承或实现

java
interface Parent {
    private void helper() {
        System.out.println("parent helper");
    }
    
    default void useHelper() {
        helper();  // ✅ 可以调用自己的私有方法
    }
}

interface Child extends Parent {
    // ❌ 不能调用 Parent 的私有方法
    // helper();
}

class Impl implements Child {
    // ❌ 也不能调用
}

new Impl().useHelper();  // ✅ 输出 "parent helper"

不能是 protected

java
interface Example {
    // ❌ 报错:Modifier 'protected' not allowed
    // protected void helper() {}
    
    // ✅ 只能是 private
    private void helper() {}
}

常见使用场景

场景一:多个默认方法共享验证逻辑

java
public interface Validator {
    default boolean validateEmail(String email) {
        return validate(email, "^[\\w.-]+@[\\w.-]+\\.\\w+$");
    }
    
    default boolean validatePhone(String phone) {
        return validate(phone, "^\\d{11}$");
    }
    
    default boolean validateId(String id) {
        return validate(id, "^[A-Z]\\d{6,10}$");
    }
    
    // 私有方法提取公共验证逻辑
    private boolean validate(String value, String regex) {
        if (value == null || value.isBlank()) {
            return false;
        }
        return value.matches(regex);
    }
}

场景二:复杂的默认方法拆解

java
public interface DataProcessor {
    default void process(List<String> data) {
        List<String> cleaned = clean(data);
        List<String> transformed = transform(cleaned);
        save(transformed);
    }
    
    private List<String> clean(List<String> data) {
        return data.stream()
            .filter(s -> !s.isBlank())
            .map(String::trim)
            .toList();
    }
    
    private List<String> transform(List<String> data) {
        return data.stream()
            .map(String::toUpperCase)
            .toList();
    }
    
    private void save(List<String> data) {
        System.out.println("Saving " + data.size() + " items");
    }
}

场景三:状态检查

java
public interface StateMachine {
    default void handleEvent(String event) {
        if (isActive()) {
            processEvent(event);
        } else {
            handleInactive(event);
        }
    }
    
    private boolean isActive() {
        return true;  // 实际场景中可能是复杂的状态检查
    }
    
    private void processEvent(String event) {
        System.out.println("Processing: " + event);
    }
    
    private void handleInactive(String event) {
        System.out.println("Ignoring (inactive): " + event);
    }
}

小结

接口私有方法是 JDK 9 的一个小功能,但解决了实际问题:

JDK 版本能力
JDK 8默认方法 + 静态方法(必须是 public)
JDK 9+新增 私有实例方法 + 私有静态方法

什么时候用它:

  • 多个默认方法有重复逻辑 → 提取成私有方法
  • 不想让实现类看到内部实现 → 私有方法隐藏细节
  • 简化默认方法的复杂度 → 拆成多个私有方法逐步处理

记住:私有方法只能在接口内部使用,不能被实现类继承或调用。

基于 VitePress 构建