Java 泛型入门

假如现在要实现一个栈(Stack)(一种用于存储数据的类),那么这个栈应该支持存储任意类型的数据,无论是 Integer、String 还是我们自己定义的数据类型。Java 泛型机制能够做到这一点。泛型也叫做参数化类型,支持泛型的类简称泛型类。

参数化类型,就是让类支持接受数据类型(类)作为参数,在创建泛型类对象的时候,我们将具体的类型传递给泛型类,进而创建出支持具体类型的类对象。

比如,假如 Stack 是泛型类,那么,我们可以将 String 类型作为参数传递给 Stack 类,以创建支持处理 String 类型的 Stack 对象。

Stack<String> stack = new Stack<String>();
stack.push("Test");
...
String next = stack.pop();

如果没有泛型,我们必须为所需要支持的每种数据类型定义(并实现)不同的 API。有了泛型,我们只需要一份 API(和一次实现)就能够处理所有类型的数据。所以泛型简化了代码。

同时,如果你尝试向支持 String 类型的 Stack 对象中添加一个 Integer 对象(或是任何其他非 String 类型的数据),你会得到一个编译时错误。所以,泛型使代码更加“静态”,减少了出错的机会。

那么如何实现一个泛型类,也就是如何运用泛型让普通类支持处理所有数据类型?

比如这是一个未实现泛型的定容栈(FixedCapacityStack)(一种初级栈),它目前只支持存储 String 类型的对象:

public class FixedCapacityStack
{
	private String[] a;
	private int N;
	
	public FixedCapacityStack(int cap) { a = new String[cap];  }
	public boolean isEmpty()           { return N == 0;        }
	public int size()                  { return N;             }
	public void push(String item)      { a[N++] = item;        }
	public String pop()                { return a[--N];        }
	public boolean isFull()            { return N == a.length; }
}

要将 FixedCapacityStack 泛型化,首先要像定义带参数函数那样在类定义中添加类型参数:

public class FixedCapacityStack<Item>
{
	...
}

相比于非泛型的类定义,上述定义多了一个 <Item>,这就是 FixedCapacityStack 类的类型参数。

加了类型参数之后,再将类中所有用到具体类型(String)的地方用 Item 代替(类似于在函数内部定义如何使用传递过来的参数):

public class FixedCapacityStack<Item>
{
	private Item[] a;
	private int N;
	
	public FixedCapacityStack(int cap) { a = (Item[]) new Object[cap]; }
	public boolean isEmpty()           { return N == 0;                }
	public int size()                  { return N;                     }
	public void push(Item item)        { a[N++] = item;                }
	public Item pop()                  { return a[--N];                }
	public boolean isFull()            { return N == a.length;         }
}

这样就实现了 FixedCapacityStack 的泛型类。

有一个注意点是,在非泛型的 FixedCapacityStack 类中,使用 a = new String[cap]; 语句创建字符串数组,而在 FixedCapacityStack<Item> 中,我们用 a = (Item[]) new Object[cap]; 语句创建泛型数组,能不能用 a = new Item[cap]; 语句来创建?不能。直接创建泛型数组在 Java 中是不允许的。

总结一下,实现一个泛型类:

第一步:在类定义中添加泛型标识 <Item>

第二步:将类中(除创建泛型数组外的)所有用到具体类型的地方用 Item 代替;

第三步:需要创建泛型数组时,使用类型转换(a = (Item[]) new Object[cap];)来间接创建泛型数组。

总结自《算法(第四版)》1.3 背包、队列和栈

posted @ 2022-01-29 10:28  Higurashi-kagome  阅读(51)  评论(0编辑  收藏  举报