泛型1:介绍及基本使用方式
前言
- 泛型实现了参数化类型的概念;
- 泛型的主要目的之一是用来指定容器要持有什么类型的对象,编译器保证类型的正确性;
- 多态也是一种泛化机制;
- 基本类型无法作为类型参数;
一.基本使用方式
泛型基本分为泛型类型和泛型方法两种,泛型类型声明方式为类型参数用尖括号括住,放在类名后边,泛型方法的参数列表应该置于返回值之前。示例如下:
//泛型类
package java.lang;
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
//泛型方法
public class GenericMethods{
public <T> void f(T t){
System.out.println(t.getClass().getName());
}
}
- 应该优先使用泛型方法,而非将泛型应用到整个类上;
- 泛型的核心概念是告诉编译器想使用什么类型,然后让编译器处理细节.
二.使用场景
1.元组类库
即当调用一个方法希望返回多个对象时,需要将一组对象直接打包存储在一个对象中——这也是元祖的概念。元组中的对象可以是不同的类型。示例代码如下:
//二维元祖
public class TwoTuple<A,B>{
public final A first;//fixme 注意是final类型的
public final B second;
public TwoTuple(A first, B second) {
this.first = first;
this.second = second;
}
}
//使用继承机制实现的三维元祖
class ThreeTuple<A,B,C> extends TwoTuple<A,B>{
public final C third;
public ThreeTuple(A first, B second, C third) {
super(first, second);
this.third = third;
}
}
- 使用继承机制实现更长的元组;
- 变量为final类型保证了元组对象被创建后,final元素便不能被改变了;
2.实现堆栈类
可以使用泛型类实现自定义的链表栈,示例如下:
package fanxing;
public class LinkedStack<T> {
private static class Node<U>{
U item;
Node<U> next;
Node(){item=null;next=null;}
public Node(U item, Node<U> next) {
this.item = item;
this.next = next;
}
//末端哨兵(end sentinel)
boolean end(){
return item==null&&next==null;
}
}
private Node<T> top=new Node<>();
//每push一次都会创建一个对象并放到栈尾
public void push(T item){
top=new Node<>(item,top);
}
public T pop(){
T result=top.item;
if(!top.end()){
top=top.next;
}
return result;
}
public static void main(String[] args) {
LinkedStack<String> lss=new LinkedStack<>();
for(String str:"du gen kui".split(" "))
lss.push(str);
String s;
while((s=lss.pop())!=null)
System.out.println(s);
}
}
3.用于工厂方法设计模式
泛型可以用于接口,比如生成器(generator),工厂方法设计模式是其一中应用。例如crawl4j中的工厂方法:
public interface WebCrawlerFactory<T extends WebCrawler> {
T newInstance() throws Exception;
}
//补充:默认工厂的实现
class DefaultWebCrawlerFactory<T extends WebCrawler> implements WebCrawlerFactory<T>{
final Class<T> claz;
DefaultWebCrawlerFactory(Class<T> clz){ this.clz=clz;}
@Override
public T newInstance() throw Exception{
try{
return clz.newInstance();
}catch(ReflectiveOperationException e){
throw e;
}
}
}
4.补充:可变参数列表
将方法参数项写成T... x
的形式就可以将其作为可变参数列表。示例如下:
public class VariableParam<T> {
public void testFunc(T... params){
for (T ele:params) {
System.out.println(ele.toString());
}
}
public static void main(String[] args) {
new VariableParam<String>().testFunc("du","gen","kui");
}
}