Java 泛型接口是指可以在接口定义中包含一个或多个类型参数的接口。泛型接口的类型参数可以在接口中的方法、属性等各种成员中使用,表示该成员可以操作多种类型的数据。
泛型接口的定义格式为:
public interface InterfaceName<T1, T2, ..., Tn> { // 接口方法 }
其中,T1, T2, …, Tn 表示泛型类型参数,可以是任何标识符。
泛型接口的类型参数可以在接口中的成员方法、成员属性等各种成员中使用,例如:
public interface List<T> { // 添加元素 void add(T element); // 获取元素 T get(int index); }
在这个示例中,List 接口是一个泛型接口,使用泛型类型参数 T 表示列表中元素的类型。在 List 接口的 add() 方法中,使用 T 类型参数来接收一个元素,并将其添加到列表中。在 get() 方法中,也使用 T 类型参数来表示获取的元素的类型。
当我们实现泛型接口时,需要指定具体的类型参数。例如:
// 泛型接口 public interface MyInterface<T> { void doSomething(T item); } // 实现接口 public class MyClass implements MyInterface<String> { @Override public void doSomething(String item) { // 实现方法逻辑 } }
在上面的示例中,MyClass 实现了 MyInterface 接口,并指定了类型参数为 String。因此,doSomething 方法的参数类型为 String。
上面介绍了类如何实现泛型接口,如果实现泛型接口的类本身也是一个泛型类呢?此时,我们可以在类的泛型中使用接口泛型参数,例如:
// ArrayList 使用了 List 接口的泛型参数 T public class ArrayList<T> implements List<T> { private T[] elements; public ArrayList(int initialCapacity) { elements = (T[]) new Object[initialCapacity]; } public void add(T element) { // 添加元素的实现 } public T get(int index) { // 获取元素的实现 return null; } }
在这个示例中,我们创建了一个 ArrayList 类,该类实现了 List 接口,并用泛型类型参数 T 指定了元素的类型。在 ArrayList 类的构造函数中,使用 T 类型参数来创建一个数组,用于存储元素。在 add() 和 get() 方法中,也使用 T 类型参数来操作列表中的元素。
泛型接口的好处是可以在编译时进行类型检查,确保类型的一致性。它还可以提高代码的重用性和灵活性,因为我们可以在不同的实现类中使用不同的类型参数。例如:
// 泛型接口 public interface MyInterface<T> { void doSomething(T item); } // 字符串实现 public class StringImpl implements MyInterface<String> { @Override public void doSomething(String item) { System.out.println("item=" + item); } } // 浮点数实现 public class FloatImpl implements MyInterface<Float> { @Override public void doSomething(Float item) { System.out.println("item=" + item); } }
上述代码中,定义了一个 MyInterface 泛型接口,StringImpl 提供了接口的字符串实现,FloatImpl 提供了接口的浮点数实现,对于同一个接口提供了不同数据类型的实现。
在 Java 中,可以使用通配符来表示泛型接口中的类型参数。通配符可以用来表示未知类型、不确定的类型或者限制类型的上界或下界。Java 中有三种通配符:
(1)?:表示未知类型。可以用来表示任意类型的参数。例如,List<?> 表示一个未知类型的List。
(2)? extends 类型:表示限制类型的上界。可以用来表示指定类型的子类或者实现类。例如,List<? extends Number> 表示一个元素类型为 Number 或者 Number的 子类的 List。
(3)? super 类型:表示限制类型的下界。可以用来表示指定类型的父类或者接口。例如,List<? super Integer> 表示一个元素类型为 Integer 或者 Integer 的父类的List。
使用通配符可以增加泛型接口的灵活性,允许在不知道具体类型的情况下操作泛型接口。通过使用通配符,可以在泛型接口中接收不同类型的参数,同时保持类型安全。
注意:使用通配符时无法进行具体类型的实例化操作,只能进行读取操作。因为通配符表示未知类型,无法确定具体的类型信息。
例如,修改上述代码的 MyInterface,定义该接口的泛型参数只能是数字,如下:
public interface MyInterface<T extends Number> { void doSomething(T item); } public class FloatImpl implements MyInterface<Float> { @Override public void doSomething(Float item) { System.out.println("item=" + item); } } public class LongImpl implements MyInterface<Long> { @Override public void doSomething(Long item) { System.out.println("item=" + item); } }
上述代码中,MyInterface 接口的泛型参数只能接收 Number 或者 Number 的子类,我们分别实现了 MyInterface 接口的 Float 和 Long 版本。