最简单易理解的Java泛型

为什么引入泛型

在JAVA中允许类型转换,但仍可能会出现ClassCastException异常,这是什么原因呢?因为Java中类型强制转换只能父类对象强制转换为子类对象,而且前提是此父类对象为子类对象实例化的结果。举个例子

Float f=(Float)new Object();//会抛出异常
Fruit apple=new Apple();
Apple newapple=(Apple)apple;//不会抛出异常,水果对象是苹果对象实例化的结果。

所以在JAVA中,对象管理是非常严格的,举个例子,一个方法,只能输出返回一种对象,这显示是不太合理的,也违反了Java多态的应用规则,所以引入了Java泛型的概念。那么什么是泛型呢!简单来说,就说把不同类型的对象组成到一起的集合。再举个例子。

public int add(int i,int j){
return i+j;
}

这个方法很明显是个相加的方法,但是有一个限制,就是能输入int类型的数据,要是其他类型的就需要进行强制转换了,那么每一个类型的相加操作都要写一个这样的方法吗?肯定不是的,这样与程序简洁的理念不相干,所以引入了泛型的概念。

集合中的泛型

List<String> list=new ArrayList<String>();

这里面,我们创建了一个List集合,用“<>”符号限制了该集合中应该放什么类型的数据,在这“<>”里面是String,所以该List集合里面只能存放List数据,这个符号里面还可以规定放多种类型的数据,这才符合Java多态的需求。比如:

Map<Integer,String> map=new HashMao<,IntegerString>();

像这个Map集合就可以存放Integer类型数据和String类型数据。这就是Java泛型最简单容易理解的概念。

定义泛型类和泛型接口

我们以一个例子来说明

public class Bag<T>{
private T content;
public Bag(T content){
this.content=content;
}
public T get(){
return this.content;
}
public void set(T content)
this.content=content;
}
public static void main(String[] args){
Bag<String> bag=new Bag<String>("mybook");
String content=bag.get();
}

在这个例子中,我们定义了泛型类,我们以“”的形式声明类型参数,在该例子中的main方法中,我们创建了bag对象,以String对象为泛型参数,这个与传统的方法相比用起来非常舒服。而且我们创建的泛型类还可以存在多个类型参数

class Bag<T1,T2,T3,....,Tn>{
}

同样的,接口也是这样的。

extends关键字限制类型参数

<T extends 类名>

这里我们用extends来限制类型参数,T必须必须是指定类或者它的子类
同样,接口也是如此。

public class LimitBag<T extends Number>{
private T content;
public LimitBag(T content){
this.content=content;
}
public T get(){
return this.content;
}
public void set(T content){
this.content=content;
}
public static void main(String[] args){
LimitBag<Integer> bag=new LimitBag<Integer>(1);//合法
LimitBag<Object> bag=new LimitBag<Object>(1)//不合法,因为Object并非是Number子类。
}
}

泛型数组

在泛型类中,我们可以定义泛型数组,注意,在类中,我们只能声明泛型数组,不能创建泛型数组实例。

public ArrayBag<T>{
//private T[] content=new T[10];错误的
private T[] content;//合法的
}

我们需要先创建一个String类型数组,然后将该数组传给泛型数组。

String[] str=new String{"1","2"};
ArrayBag<String> arraybag=new ArrayBag<String>();
arratbag.content=str;

定义泛型方法

凡是方法参数或者返回值带有类型参数"<>"的方法都属于泛型方法。
泛型方法不像泛型数组一样,任何类都可以构建泛型方法,一开始我们谈泛型的时候,就是通过泛型方法。泛型方法就是方法参数和返回值可以为不同类型的参数,举个例子。

public static <E> void printArray(E[] array){
for(E element:array)
System.out.println(element);
}

这就是一个泛型方法,输入可以是个String类型数组,可以是个int类型数组。

通配符“?”

通配符“?”可以和extends配合使用设置限制,其实这是一个上限,同样的,通配符还可以与super关键字一起用设置下限,和泛型还存在下限;而且通配符还表示任何类型的对象。

// 表示collection集合内可以存放任意类型的元素
public static void printNew(Collection<?> collection){
for(Object obj:collection)
System.out.println(obj);
}
TreeSet<? extends Number> x=new TreeSet<Integer>();//设置下限,Integer是Number的子类
TreeSet<? super Integer> y=new TreeSet<Number>();//设置上限,Number是Integer的父类

注意事项

  1. 在程序运行时,泛型类是被所有这种类的实例共享的。比如,ArrayList<String>、ArrayList<Integer>在编辑时被看作不同的类,但是在编译后,泛型标签会被擦除,这两个都是ArrayList类
List<String> l1=new List<String>();
List<Integer> l2=new List<Integer>();
boolean b1=l1.getclass()==l2.getclass();//b1得true
  1. 使用泛型时,编辑器不允许在同一个类中定义两个同名的方法
  2. 不允许队确切的泛型类型使用instanceof操作,会抛出异常。
  3. 不能对泛型类型进行强制类型转换,会抛出异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值