Java 泛型在接口、抽象类与继承中的应用

1. 泛型接口

在 Java 中,接口 也可以使用泛型,使其方法的返回值或参数类型能够在实现类中进行确定。例如:

public interface Study<T> {
    T test();
}
  • 这里的 Study<T> 是一个泛型接口,T 作为类型参数,在使用时需要具体化。
  • 泛型接口的实现方式可以是明确泛型类型,也可以继续使用泛型,交给实例化对象来决定。

2. 明确泛型类型的实现

如果子类在实现接口时是一个普通类,可以直接明确泛型类型。例如:

public class Main {
    public static void main(String[] args) {
        A a = new A();
        Integer i = a.test(); // 返回 Integer 类型
    }

    static class A implements Study<Integer> {
        // 明确指定泛型类型为 Integer
        @Override
        public Integer test() {
            return null;
        }
    }
}

特点:

✅ 代码清晰,使用时无需再指定类型。
✅ 适用于泛型类型在实现类层面已经确定的情况。


3. 继续使用泛型,让实例化时决定类型

如果子类仍然是一个泛型类,可以继续使用泛型,让具体对象来决定类型:

public class Main {
    public static void main(String[] args) {
        A<String> a = new A<>();
        String i = a.test(); // 返回 String 类型
    }

    static class A<T> implements Study<T> {
        // 继续使用泛型,类型由对象创建时决定
        @Override
        public T test() {
            return null;
        }
    }
}

特点:

✅ 代码更加灵活,允许不同实例使用不同的类型。 ✅ 适用于泛型类型在实例化时才决定的情况。


4. 泛型在抽象类中的使用

不仅仅是接口,抽象类 也可以使用泛型。例如:

public abstract class Animal<T> {
    // 泛型成员变量
    private T data;

    public Animal(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
    
    // 抽象方法,子类必须实现
    public abstract void makeSound();
}

子类在继承时可以:

方式 1:明确泛型类型

public class Dog extends Animal<String> {
    public Dog(String data) {
        super(data);
    }

    @Override
    public void makeSound() {
        System.out.println("汪汪汪!");
    }
}

方式 2:继续使用泛型

public class WildAnimal<T> extends Animal<T> {
    public WildAnimal(T data) {
        super(data);
    }

    @Override
    public void makeSound() {
        System.out.println("未知动物的叫声");
    }
}
  • Dog 明确 了泛型类型为 String
  • WildAnimal<T> 仍然使用 泛型,类型由具体实例决定。

使用示例:

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("哈士奇");
        System.out.println(dog.getData()); // 输出: 哈士奇
        dog.makeSound(); // 输出: 汪汪汪!

        WildAnimal<Integer> tiger = new WildAnimal<>(100);
        System.out.println(tiger.getData()); // 输出: 100
        tiger.makeSound(); // 输出: 未知动物的叫声
    }
}

5. 多个泛型参数的支持

如果需要多个泛型参数,可以使用 多个类型变量

public interface Pair<K, V> {
    K getKey();
    V getValue();
}

实现类可以:

public class KeyValuePair<K, V> implements Pair<K, V> {
    private K key;
    private V value;

    public KeyValuePair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public K getKey() {
        return key;
    }

    @Override
    public V getValue() {
        return value;
    }
}

使用时可以指定不同的泛型参数:

public class Main {
    public static void main(String[] args) {
        KeyValuePair<String, Integer> pair = new KeyValuePair<>("年龄", 25);
        System.out.println(pair.getKey() + ": " + pair.getValue()); // 输出: 年龄: 25
    }
}

6. 泛型的约束(限定泛型类型)

有时候,我们希望泛型只能是某些特定类型,例如只允许 Number 及其子类。

public class NumberBox<T extends Number> {
    private T value;

    public NumberBox(T value) {
        this.value = value;
    }

    public double doubleValue() {
        return value.doubleValue();
    }
}

这样,如果尝试创建 NumberBox<String>编译时就会报错

NumberBox<Integer> intBox = new NumberBox<>(10); // ✅ 正确
NumberBox<Double> doubleBox = new NumberBox<>(10.5); // ✅ 正确
NumberBox<String> strBox = new NumberBox<>("Hello"); // ❌ 编译错误!

总结

泛型应用方式 1(确定泛型)方式 2(继续使用泛型)
接口class A implements Study<Integer>class A<T> implements Study<T>
抽象类class Dog extends Animal<String>class WildAnimal<T> extends Animal<T>
继承class Child extends Parent<Integer>class Child<T> extends Parent<T>

如果泛型类型在实现时已确定,就直接指定类型
如果类型不确定,可以继续使用泛型,让实例化时再指定类型

通过 泛型接口、泛型抽象类、泛型继承,Java 可以提供更灵活、类型安全的代码结构,提高代码的复用性和可维护性! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值