default 关键字

概述

default 关键字在Java中有两个主要用途:

  1. 在switch语句中作为默认分支,当所有case都不匹配时执行
  2. 在接口中定义默认方法(Java 8+)

语法格式

// switch语句中的default
switch (表达式) {
    case1:
        // 代码
        break;
    default:
        // 默认代码
}

// 接口中的默认方法
interface InterfaceName {
    default returnType methodName() {
        // 默认实现
    }
}

switch中的default

public class DefaultSwitchExample {

    // 基本default使用
    public static void processGrade(char grade) {
        switch (grade) {
            case 'A':
                System.out.println("优秀");
                break;
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("中等");
                break;
            case 'D':
                System.out.println("及格");
                break;
            case 'F':
                System.out.println("不及格");
                break;
            default:
                System.out.println("无效等级: " + grade);
        }
    }

    // 数字范围处理
    public static void categorizeNumber(int number) {
        switch (number / 10) {
            case 0:
                System.out.println(number + " 在 0-9 范围内");
                break;
            case 1:
                System.out.println(number + " 在 10-19 范围内");
                break;
            case 2:
                System.out.println(number + " 在 20-29 范围内");
                break;
            case 3:
                System.out.println(number + " 在 30-39 范围内");
                break;
            default:
                if (number < 0) {
                    System.out.println(number + " 是负数");
                } else {
                    System.out.println(number + " 大于等于40");
                }
        }
    }

    // 月份天数(default处理无效月份)
    public static int getDaysInMonth(int month) {
        switch (month) {
            case 1: case 3: case 5: case 7: case 8: case 10: case 12:
                return 31;
            case 4: case 6: case 9: case 11:
                return 30;
            case 2:
                return 28; // 简化处理,不考虑闰年
            default:
                System.out.println("无效的月份: " + month);
                return -1;
        }
    }

    public static void main(String[] args) {
        System.out.println("=== 成绩等级处理 ===");
        processGrade('A');
        processGrade('B');
        processGrade('X'); // 触发default

        System.out.println("\n=== 数字分类 ===");
        categorizeNumber(5);
        categorizeNumber(15);
        categorizeNumber(25);
        categorizeNumber(-10); // 触发default
        categorizeNumber(50);  // 触发default

        System.out.println("\n=== 月份天数 ===");
        for (int i = 1; i <= 13; i++) {
            int days = getDaysInMonth(i);
            if (days > 0) {
                System.out.println("第" + i + "月有" + days + "天");
            }
        }
    }
}

接口默认方法

// 定义带默认方法的接口
interface Drawable {
    // 抽象方法
    void draw();

    // 默认方法
    default void setColor(String color) {
        System.out.println("设置颜色为: " + color);
    }

    default void displayInfo() {
        System.out.println("这是一个可绘制的对象");
        System.out.println("支持的操作: 绘制、设置颜色");
    }

    default double calculateArea() {
        System.out.println("未实现面积计算");
        return 0.0;
    }
}

interface Movable {
    void move(int x, int y);

    default void moveBy(int deltaX, int deltaY) {
        System.out.println("相对移动: (" + deltaX + ", " + deltaY + ")");
        // 这里可以调用抽象方法
        // move(getCurrentX() + deltaX, getCurrentY() + deltaY);
    }

    default void reset() {
        System.out.println("重置位置到原点");
        move(0, 0);
    }
}

// 实现类
class Circle implements Drawable, Movable {
    private double radius;
    private int x, y;

    public Circle(double radius) {
        this.radius = radius;
        this.x = 0;
        this.y = 0;
    }

    @Override
    public void draw() {
        System.out.println("绘制半径为 " + radius + " 的圆形在位置 (" + x + ", " + y + ")");
    }

    @Override
    public void move(int x, int y) {
        this.x = x;
        this.y = y;
        System.out.println("圆形移动到位置 (" + x + ", " + y + ")");
    }

    // 重写默认方法
    @Override
    public double calculateArea() {
        double area = Math.PI * radius * radius;
        System.out.println("圆形面积: " + String.format("%.2f", area));
        return area;
    }

    // 可以选择不重写其他默认方法,直接使用接口提供的实现
}

class Rectangle implements Drawable {
    private double width, height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("绘制 " + width + "x" + height + " 的矩形");
    }

    @Override
    public double calculateArea() {
        double area = width * height;
        System.out.println("矩形面积: " + area);
        return area;
    }

    // 使用接口的默认setColor和displayInfo方法
}

public class DefaultMethodExample {
    public static void main(String[] args) {
        Circle circle = new Circle(5.0);
        Rectangle rectangle = new Rectangle(10.0, 6.0);

        System.out.println("=== 圆形操作 ===");
        circle.draw();
        circle.setColor("红色");      // 使用默认方法
        circle.displayInfo();         // 使用默认方法
        circle.calculateArea();       // 使用重写的方法
        circle.move(10, 20);
        circle.moveBy(5, 5);          // 使用默认方法
        circle.reset();               // 使用默认方法

        System.out.println("\n=== 矩形操作 ===");
        rectangle.draw();
        rectangle.setColor("蓝色");   // 使用默认方法
        rectangle.displayInfo();      // 使用默认方法
        rectangle.calculateArea();    // 使用重写的方法
    }
}

默认方法的冲突解决

interface InterfaceA {
    default void commonMethod() {
        System.out.println("InterfaceA的默认实现");
    }

    default void methodA() {
        System.out.println("方法A");
    }
}

interface InterfaceB {
    default void commonMethod() {
        System.out.println("InterfaceB的默认实现");
    }

    default void methodB() {
        System.out.println("方法B");
    }
}

// 实现多个接口时的冲突解决
class ConflictResolver implements InterfaceA, InterfaceB {

    // 必须重写冲突的方法
    @Override
    public void commonMethod() {
        System.out.println("ConflictResolver的实现");

        // 可以选择调用特定接口的默认方法
        InterfaceA.super.commonMethod();
        InterfaceB.super.commonMethod();
    }

    // 非冲突的默认方法可以直接使用
    // methodA() 和 methodB() 可以直接使用
}

// 另一种解决方案:选择其中一个接口的实现
class ConflictResolver2 implements InterfaceA, InterfaceB {

    @Override
    public void commonMethod() {
        // 选择使用InterfaceA的实现
        InterfaceA.super.commonMethod();
    }
}

public class DefaultMethodConflictExample {
    public static void main(String[] args) {
        System.out.println("=== 冲突解决方案1 ===");
        ConflictResolver resolver1 = new ConflictResolver();
        resolver1.commonMethod();
        resolver1.methodA();
        resolver1.methodB();

        System.out.println("\n=== 冲突解决方案2 ===");
        ConflictResolver2 resolver2 = new ConflictResolver2();
        resolver2.commonMethod();
        resolver2.methodA();
        resolver2.methodB();
    }
}

实际应用示例

import java.util.*;
import java.util.function.Predicate;

// 数据处理接口
interface DataProcessor<T> {
    // 抽象方法
    List<T> process(List<T> data);

    // 默认过滤方法
    default List<T> filter(List<T> data, Predicate<T> condition) {
        List<T> result = new ArrayList<>();
        for (T item : data) {
            if (condition.test(item)) {
                result.add(item);
            }
        }
        System.out.println("过滤前: " + data.size() + " 项,过滤后: " + result.size() + " 项");
        return result;
    }

    // 默认排序方法
    default List<T> sort(List<T> data, Comparator<T> comparator) {
        List<T> result = new ArrayList<>(data);
        result.sort(comparator);
        System.out.println("数据已排序");
        return result;
    }

    // 默认统计方法
    default void printStatistics(List<T> data) {
        System.out.println("数据统计:");
        System.out.println("  总数量: " + data.size());
        System.out.println("  是否为空: " + data.isEmpty());
        if (!data.isEmpty()) {
            System.out.println("  第一项: " + data.get(0));
            System.out.println("  最后一项: " + data.get(data.size() - 1));
        }
    }
}

// 数字处理器
class NumberProcessor implements DataProcessor<Integer> {
    @Override
    public List<Integer> process(List<Integer> data) {
        System.out.println("处理数字数据...");
        List<Integer> result = new ArrayList<>();
        for (Integer num : data) {
            if (num != null) {
                result.add(num * 2); // 数字乘以2
            }
        }
        return result;
    }

    // 可以添加特定的方法
    public List<Integer> filterEven(List<Integer> data) {
        return filter(data, num -> num % 2 == 0);
    }

    public List<Integer> sortAscending(List<Integer> data) {
        return sort(data, Integer::compareTo);
    }
}

// 字符串处理器
class StringProcessor implements DataProcessor<String> {
    @Override
    public List<String> process(List<String> data) {
        System.out.println("处理字符串数据...");
        List<String> result = new ArrayList<>();
        for (String str : data) {
            if (str != null && !str.trim().isEmpty()) {
                result.add(str.trim().toUpperCase());
            }
        }
        return result;
    }

    public List<String> filterByLength(List<String> data, int minLength) {
        return filter(data, str -> str.length() >= minLength);
    }

    public List<String> sortByLength(List<String> data) {
        return sort(data, Comparator.comparing(String::length));
    }
}

public class DefaultMethodApplicationExample {
    public static void main(String[] args) {
        // 数字处理示例
        System.out.println("=== 数字处理 ===");
        NumberProcessor numberProcessor = new NumberProcessor();
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        System.out.println("原始数据: " + numbers);
        numberProcessor.printStatistics(numbers); // 使用默认方法

        List<Integer> processedNumbers = numberProcessor.process(numbers);
        System.out.println("处理后: " + processedNumbers);

        List<Integer> evenNumbers = numberProcessor.filterEven(processedNumbers);
        System.out.println("偶数: " + evenNumbers);

        List<Integer> sortedNumbers = numberProcessor.sortAscending(Arrays.asList(9, 3, 7, 1, 5));
        System.out.println("排序后: " + sortedNumbers);

        // 字符串处理示例
        System.out.println("\n=== 字符串处理 ===");
        StringProcessor stringProcessor = new StringProcessor();
        List<String> strings = Arrays.asList("hello", "world", "java", "programming", "default", "method");

        System.out.println("原始数据: " + strings);
        stringProcessor.printStatistics(strings); // 使用默认方法

        List<String> processedStrings = stringProcessor.process(strings);
        System.out.println("处理后: " + processedStrings);

        List<String> longStrings = stringProcessor.filterByLength(strings, 5);
        System.out.println("长度>=5的字符串: " + longStrings);

        List<String> sortedByLength = stringProcessor.sortByLength(strings);
        System.out.println("按长度排序: " + sortedByLength);
    }
}

最佳实践

public class DefaultBestPractices {

    // 1. switch中的default应该处理所有未预期的情况
    public static String getHttpStatusMessage(int statusCode) {
        switch (statusCode) {
            case 200:
                return "OK";
            case 201:
                return "Created";
            case 400:
                return "Bad Request";
            case 401:
                return "Unauthorized";
            case 404:
                return "Not Found";
            case 500:
                return "Internal Server Error";
            default:
                // 好的做法:提供有意义的默认处理
                return "Unknown Status Code: " + statusCode;
        }
    }

    // 2. 接口默认方法应该提供合理的默认实现
    interface Cache<K, V> {
        V get(K key);
        void put(K key, V value);

        // 好的默认方法:提供常用功能的默认实现
        default boolean containsKey(K key) {
            return get(key) != null;
        }

        default V getOrDefault(K key, V defaultValue) {
            V value = get(key);
            return value != null ? value : defaultValue;
        }

        default void putIfAbsent(K key, V value) {
            if (!containsKey(key)) {
                put(key, value);
            }
        }

        // 好的默认方法:提供工具方法
        default void printStats() {
            System.out.println("缓存统计信息");
            // 默认实现可以调用抽象方法
        }
    }

    // 3. 避免在default中添加复杂逻辑
    interface Service {
        void start();
        void stop();

        // 好的做法:简单的默认实现
        default boolean isRunning() {
            return false; // 简单的默认返回值
        }

        // 好的做法:组合其他方法
        default void restart() {
            stop();
            start();
        }

        // 避免:复杂的业务逻辑
        /*
        default void complexOperation() {
            // 大量复杂的业务逻辑...
            // 这样的逻辑应该放在实现类中
        }
        */
    }

    // 4. switch的default位置
    public static void processOption(int option) {
        switch (option) {
            case 1:
                System.out.println("选项1");
                break;
            case 2:
                System.out.println("选项2");
                break;
            case 3:
                System.out.println("选项3");
                break;
            default: // 通常放在最后
                System.out.println("无效选项: " + option);
                break;
        }
    }

    public static void main(String[] args) {
        System.out.println("=== HTTP状态码 ===");
        System.out.println("200: " + getHttpStatusMessage(200));
        System.out.println("404: " + getHttpStatusMessage(404));
        System.out.println("999: " + getHttpStatusMessage(999)); // 触发default

        System.out.println("\n=== 选项处理 ===");
        processOption(1);
        processOption(2);
        processOption(99); // 触发default
    }
}

default关键字在switch语句中提供了重要的错误处理机制,在接口中则支持了向后兼容的功能扩展。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 16:25:54

results matching ""

    No results matching ""