泛型的简单介绍以应用

1,泛型的定义

泛型也成为“参数化类型”,我们可以理解为在定义的时候由具体的类型参数化,

似与函数的变量参数,调用时传入具体的参数来调用。

泛型的本质是为了参数化类型,也就是在不创建新的类型情况下,通过泛型指定不同

的类型的形参具体控制限制的类型。

2,泛型的引出

在学习栈的时候我们常用的是int类型定义的栈,只能存放整数类型,但实际中我们需

要将各种类型的数据放入栈中,所以我们想到了通用栈

class ObjectStack{
	private Object elem[];
	private int top;
	
	public ObjectStack(){
		this(10);
	}
	public ObjectStack(int size){
		this.elem = new Object[size];
		this.top = 0;
	}
	public void push(Object val){
		this.elem[this.top++] = val;
	}
	public void pop(){
		--this.top;
	}
	public Object gettop(){
		return this.elem[this.top-1];
	}
}
public static void main(String[] args) {
		ObjectStack s1 = new ObjectStack(10);
		s1.push(10);
		s1.push(20);
		s1.push("hello");
		
		double data = (double)s1.gettop();//必须强转为double类型
	}

注意到我们获取栈顶的时候必须要强转类型才能输出,不然会报错,为了解决这样的

问题(在编译期间),于是我们应用出了泛型

3.泛型的使用

首先,我们定义一个泛型栈

class GenericStack<T>{
	private T elem[];
	private int top;
	
	
	public GenericStack(){
		this(10);
	}
	public GenericStack(int size){
		this.elem = (T[])new Object[size];
		this.top = 0;
	}
	
	public void push(T val){
		this.elem[this.top++] =  val;
	}
	
	public void pop(){
		--this.top;
	}
	
	public T gettop(){
		return this.elem[this.top-1];
	}
}
GenericStack<Integer> s1 = new GenericStack<Integer>(10);
		s1.push(10);
		s1.push(20);
		
		s1.push("hello");//报错


放我们想要将hello装进栈的时候会报错,不会再有通用栈需要强转的问题。

那到底是怎么实现的?这就涉及到了泛型的意义:

(1)在编译期间就对类型进行检查。

(2)<T>是一个占位符,当我们输入具体类型,会进行自动类型转换(如我们定义的

Integer)

4,深究泛型

我们进一步对泛型进行研究

GenericStack<Integer> s1 = new GenericStack<Integer>(10);
		System.out.println(s1);
		GenericStack<String> s2 = new GenericStack<String>(10);
		System.out.println(s2);
		System.out.println(s1.getClass()==s2.getClass());

输出观察


我们可以看出<>中的类型对类的属性根本没有影响。这就说到了泛型的擦除机制

擦除机制:首先我们说过泛型在编译期间就判断变量类型,然后运行时会向上擦除变

量---》往基类的方向,最终都会被擦除为Object类型。

这个时候就有一个问题,我不想擦除到Object类型怎么办???

我们举例说明,找最大值

class GenericAlg<T>{//擦除到Comparable位置 Object没有comparTo接口
	public T findMaxVal(T[]array){
		
		T maxval = array[0];
		for(int i = 0;i< array.length;i++){
			if(maxval.compareTo(array[i])<0){//两个对象比较用compareTo方法,报错
				maxval = array[i];
			}
		}
		return maxval;
	}
}

因为是两个对象比较,所以我们要用compareTo方法来比较,可是我们发现报错了,

这是因为Object类型没用compareTo方法,这就说到我们泛型的上界,我们不想让它

擦除到Object类型,我们就要找到一个上界可以调用compareTo方法的上界。

class GenericAlg<T extends Comparable<T>>{//擦除到Comparable位置

要注意的是泛型只有上界,没有下界

这就还有个问题,如果我想通过类名直接调用fingMaxVal()方法???

简单我们可以定义static类型的方法,但是问题又来了,static方法不依赖于参数类型

与对象,我们想要返回泛型类型会报错,这个时候我们就要把static默认为泛型类型

class GenericAlg2<T>{
	public static<T extends Comparable<T>> T findMaxVal(T array[]){
		T maxval = array[0];
		for(int i = 0;i< array.length;i++){
			if(maxval.compareTo(array[i])<0){//两个对象比较用compareTo方法
				maxval = array[i];
			}
		}
		return maxval;
	}
	
}

5,泛型中的坑

泛型中的坑总是让人防不胜防,所以我们来讲解几种最常见最容易踩到的坑:

 * 1.不能new泛型类型的数组 new T[];

 * 2.能不能new泛型类型的对象   不能 T jet = new T(); 需要指定类型

 * 3.能不能得到泛型类型的对象数组  不能 GenericStack<Integer> s3[] = new 

GenericStack<Integer>(10);

 * 4.简单类型不能作为泛型的参数   类型擦除机制往基类擦  简单类型没有基类

 * 5.在static的方法中不能用泛型类型的参数  

    static 定义的方法不依赖与对象 无法指定当前类型对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值