泛型
泛型:是一种未知的数据类型,当我们不知道要是用什么样的数据类型的时候,可以使用泛型。泛型我们也可以看做是一个变量,用来接收数据类型。
E e:element 元素
T t: type 类型
ArrayList在定义集合的时候,不知道在集合当中存储什么类型的数据,所以类型使用泛型。E: 未知的数据类型。
概述:可以在类中或方法当中预知的使用未知的数据类型。一般在创建对象的时候,将未知的数据类型确定为具体的数据类型,当没有指定泛型时,默认类型是Object。
使用泛型的好处
- 避免了类型转换的麻烦,存储的是什么样的数据类型,取出的就是什么样的数据类型。
- 把运行时异常(代码运行之后会抛出异常)提升到编译器阶段(写代码时就报错)。
备注:泛型其实也是数据类型的一部分,一般我们将类名与泛型合并在一起看做数据类型。
泛型的定义和使用
泛型用来灵活的将数据类型应用到不同的类,方法,接口当中,将书库类型作为参数进行传递。
定义
修饰符 class 类名<代表泛型的变量>{
// ....
}
例如
public class ArrayList<E>{
public boolean add(E e){
}
public E get(int index){
}
//...
}
备注: 定义的时候使用未知的泛型的变量,使用的需要确定泛型具体类型。
定义并使用含有泛型的方法
定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(泛型参数){}
例如:
public class GenericMethod{
//带有泛型的方法
public <VIP> void show(VIP vip){
System.out.println(vip);
}
//定义一个含有泛型的返回值
public <VIP> VIP show02(VIP vip){
//...
return vip;
}
}
public class Test{
public static void main(String []args){
//创建对象
GenericMethod gm=new GenericMethod();
//调用带有泛型的方法
gm.show("abc");//VIP vip 形参 String str str="abc"
gm.show(123);// VIP--->Integer vip=123;
}
}
定义并使用泛型的接口
定义格式:
修饰符 interface 接口名 <代表泛型的变量>{}
例如:
public interface Collection<E>{
public void add(E e);
public Iterator<E> iterator();
}
//自定义一个泛型接口
public interface AInterface<T>{
public abstract void add(T t);
public abstract T get();
//....
}
使用格式:
1.定义实现类是可以确定泛型的类型
public class Test implements AInterface<String>{
@ Override
public void add(T t){
//....
}
@ Override
public String get(){
//.....
}
}
备注:此时泛型的值就是String类型
2.1始终不知道泛型的类型,直到创建对象的时候才可以确定。
public class MyInterfaceimpl02<T> implements AInterface<T>{
@ Override
public void add(T t){
//....
}
@ Override
public T get(){
//.....
}
}
2.2确定泛型
/*
使用泛型
*/
public class Demo04Generic{
public static void main(String []args){
MyInterface<String> my=new MyInterfaceImpl<String>();
my.add("abc");
}
}
泛型的通配符
当使用泛型类或者泛型接口的时候,传递的数据中,泛型的类型不确定,我们可以通过通配符<?>,一旦使用泛型通配符之后,就只能使用Object类中的共性方法,集合当中元素自身的方法无法使用。
通配符的基本使用
当不知道使用什么类型来接收的时候,此时可以使用<?>来表示,代表未知的通配符。此时只能接受数据,不能往该集合中存储数据。
public static void main(String []args){
//可以存储整数的集合
Collection<Integer> list= new ArrayList<>();
//此时list可以存储整数的数据
//展示list集合当中的数据
gerElement(list);
//存储String字符串的集合
Collection<String> list2=new ArrayList<>();
//此时list可以存储字符串的数据
}
public static void gerElement( Collection<?> coll){
//可以接收Integer数据
//此时? 可以代表任意类型
}
备注:泛型不存在继承关系。
通配符的高级用法—受限泛型
之前使用泛型的时候,实际上是可以直接设置的,只要是类就可以,但是在java的泛型中,还可以指定一个泛型上限和下限。
泛型的上限
- 格式: 类型名称<? extends 类名>对象名
- 意义:只能接收该类型及其子类
泛型的下限
- 格式:类型名称<? super 类名>对象名
- 意义:只能接收该类型及其父类
比如说:已知顶级父类Object String Integer Number ,Integer是Number的子类。
public static void main(String []args){
Collection<Integer> list1=new ArrayList<>();
Collection<String> list2=new ArrayList<>();
Collection<Number> list3=new ArrayList<>();
Collection<Object> list4=new ArrayList<>();
}
//定义方法 可以接收任意类型
public static void getElement(Collection<?> coll){
//...
}
//定义方法,只能接收数字类型 Number类和它的子类
public static void getElement(Collection <? extends Number> coll){
//...
}
//定义方法,接收Number类型及其以上类型
public static void getElement(Collection<? super Number> coll){
//...
}