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 可以提供更灵活、类型安全的代码结构,提高代码的复用性和可维护性! 🚀