Java中的泛型(附带实例)
泛型(Generics)是 Java 语言引入的一个非常重要的机制,它允许程序在编译阶段检查类型是否非法,进而可以避免类型转换失败的风险。
泛型一般应用于方法和类,被声明了泛型的方法和类可以不明确指定某个类型,它就好比模板,可以匹配多种类型。
我们先了解一下泛型标记符,这些标记符用于表示不同的类型,它能匹配传入的任意 Java 类型。常见的泛型标记符如下:
实际上 Java 并没有限定只能用以上这些符号作为泛型标记符,我们可以使用 A~Z 中的任意一个英文字母作为标记符,编译器也能编译成功。之所以提出以上五个标记符是为了增加代码的可读性,这只是一种开发约定。
下面来看泛型方法的语法,其实就是在普通方法中添加泛型标记符,同时参数列表的类型也要使用泛型标记符:
下面是泛型方法的 7 个示例:
如果需要,我们还可以在一个方法中声明多个泛型标记符。比如下面的两个示例,每个方法都同时声明了 T 和 E 两个泛型参数:
根据上述泛型方法的语法编写下面的实例:
注意对于基本数据类型,编译器会自动转换成对应的包装类,比如“10.11”会转换为 Double 类型,而“10”则会转换为 Integer 类型。
泛型类型的语法如下,其实就是在普通类的类名后面添加泛型标记符:
根据泛型类型语法我们来看下面的实例:
比如在下面的实例中定义一个 MyInterface<T> 泛型接口,里面包含了一个 test(T t)泛型方法,我们就可以在实现接口时指定类型,比如 MyInterface<String> 和 MyInterface<int[]>。
泛型一般应用于方法和类,被声明了泛型的方法和类可以不明确指定某个类型,它就好比模板,可以匹配多种类型。
我们先了解一下泛型标记符,这些标记符用于表示不同的类型,它能匹配传入的任意 Java 类型。常见的泛型标记符如下:
- E:即 Element,用于表示集合元素的类型;
- T:即 Type,用于表示常规类型;
- K:即 Key,用于表示键值对中键的类型;
- V:即 Value,用于表示键值对中值的类型;
- N:即 Number,用于表示数值类型。
实际上 Java 并没有限定只能用以上这些符号作为泛型标记符,我们可以使用 A~Z 中的任意一个英文字母作为标记符,编译器也能编译成功。之所以提出以上五个标记符是为了增加代码的可读性,这只是一种开发约定。
Java泛型方法
泛型方法是指一个方法具备了泛型的机制,它可以接收不同类型的参数,在调用时传入任意类型的参数,编译器能够根据不同类型的参数处理不同类型的方法调用。下面来看泛型方法的语法,其实就是在普通方法中添加泛型标记符,同时参数列表的类型也要使用泛型标记符:
访问修饰符 非访问修饰符 <泛型标记符> 返回类型 方法名(参数列表){
方法体
}
下面是泛型方法的 7 个示例:
public <T> String join(T t) public <T> T join(T t) public <T> String join(T t,int num) public <T> String join(int num,T t) public <T> void join(T t) public static <T> String join(T t) public <E> void printArray(E[] arr)仔细观察它与普通方法之间的差异,其中的 T 和 E 就是泛型标记符,参数列表中的泛型参数不影响其他参数,顺序也可以根据需要确定。此外,方法的返回值类型也可以用泛型标记符表示。
如果需要,我们还可以在一个方法中声明多个泛型标记符。比如下面的两个示例,每个方法都同时声明了 T 和 E 两个泛型参数:
public <T,E> String join(T t,E e) public <T,E> String join(T t,E e,int num)
根据上述泛型方法的语法编写下面的实例:
public class GenericsTest {
public static void main(String[] args) {
print(10.11, "Double");
print(10, "Integer");
print("hello", "String");
}
public static <E> void print(E e, String s) {
if (s.equals("Double"))
System.out.println("E is a Double type : " + e);
if (s.equals("Integer"))
System.out.println("E is a Integer type : " + e);
if (s.equals("String"))
System.out.println("E is a String type : " + e);
}
}
输出结果为:
E is a Double type : 10.11
E is a Integer type : 10
E is a String type : hello
注意对于基本数据类型,编译器会自动转换成对应的包装类,比如“10.11”会转换为 Double 类型,而“10”则会转换为 Integer 类型。
Java泛型类型
泛型类型是指一个类具备了泛型的机制,它可以接收不同类型的参数,在创建对象时传入指定类型的参数。泛型类型的语法如下,其实就是在普通类的类名后面添加泛型标记符:
访问修饰符 class 类名<泛型标记符>{
}
下面是泛型类型定义的例子,可以在类名后面添加 <E> 使类具备泛型机制,当然也支持多个类型参数,即用多个泛型标记符来表示,比如 <E,T,K,V>。
public class GenericsTest<E> public class GenericsTest<E,T,K,V>
根据泛型类型语法我们来看下面的实例:
public class GenericsTest {
public static void main(String[] args) {
String data2 = "hello world";
Info data3 = new Info("200", true);
Result<String> r2 = new Result<String>(data2);
Result<Info> r3 = new Result<Info>(data3);
System.out.println(r2);
System.out.println(r3);
}
}
class Result<T> {
T data;
public Result(T t) {
this.data = t;
}
public String toString() {
return data.toString();
}
}
class Info {
String code;
boolean isSuccess;
public Info(String s, boolean b) {
this.code = s;
this.isSuccess = b;
}
public String toString() {
return code + "-" + isSuccess;
}
}
输出结果为:
hello world
200-true
Java泛型接口
类似地,我们也可以定义泛型接口,它能让一个普通接口具有泛型的能力。比如在下面的实例中定义一个 MyInterface<T> 泛型接口,里面包含了一个 test(T t)泛型方法,我们就可以在实现接口时指定类型,比如 MyInterface<String> 和 MyInterface<int[]>。
public class GenericsTest {
public static void main(String[] args) {
new MyImplement().test("hello");
new MyImplement2().test(new int[] { 1, 2, 3, 4, 5 });
}
}
interface MyInterface<T> {
public abstract void test(T t);
}
class MyImplement implements MyInterface<String> {
public void test(String s) {
System.out.println(s);
}
}
class MyImplement2 implements MyInterface<int[]> {
public void test(int[] arr) {
System.out.println(Arrays.toString(arr));
}
}
输出结果为:
hello
[1, 2, 3, 4, 5]
ICP备案:
公安联网备案: