泛型

泛型(不允许继承

概述

  • 泛型:可以再类或者方法当中预知的使用未知的数据里类型。

  • 备注:一般在创建对象的时候,将未知的数据确定为具体的数据类型,当没有指定泛型,默认类型为Object类型。
    E e:Element 元素
    T t:Type 类型
    ArrayList在定义集合的时候,不知道集合当中存储什么样的数据类型,所以类型使用泛型
    E:位置的数据类型

  • 备注

    创建集合对象的时候,就一定确定数据类型
        ArrayList<String> list = new ArrayList<E>();
    会把数据类型作为参数进行传递,把String数据类型赋值给泛型
        列:
       public class ArrayList<E e>{
            public boolean add(E e){}
            public E  get(int index){}
        }
    
        ArrayList<String> list = new ArrayList<E>();//创建集合
    
        public class ArrayList<String>{
            public boolean add(String e){}
            public String get(int index){}
        }
    


集合中使用泛型总结

  1. 集合接口或者集合类在jdk5.0时都修改为带泛型的结构。

  2. 在实例化集合类时,可以指明具体的泛型类型

  3. 指明完以后,在集合类或者接口中凡是定义类或者接口时,内部结构(比如方法,构造器,属性等)使用到泛型的位置,都指定为实例化的泛型类型

    比如:add(E e) ———>实例化以后:add(Integer e)

  4. 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换

  5. 如果实例化时,没有指明泛型的类型。默认类型为java.Lang.Object类型

  • 使用泛型和不使用泛型的区别

     * 创建对象的时候不使用泛型
     * 好处:
     *        可以存储任意类型的数据,默认的类型是Object
     * 弊端:
     *      不安全,伴随着引发异常
     ****************************************************
     * 创建对象的时候使用泛型
     * 好处:
     *      1.避免了类型转换的麻烦,存储的什么类型,取出的就是什么数据类型
     *      2.把运行期异常(代码运行的时候)提升到了编译期阶段(写代码的时候)
     * 弊端:
     *      泛型是什么样的类型,只能存储什么样的数据类型
         //备注:泛型其实是数据类型的一部分,一般我们将类名和泛型合并一起看做数据类型。
    

泛型的定义与使用

  • 泛型;可以灵活的将数据类型引用到不同的类,方法,接口当中。将数据类型作为参数进行传递。
    因为我们的集合框架的体系中,大量的使用了泛型。

定义和使用泛型的类

定义格式

修饰符 class 类名<代表泛型的变量>{
    //...
}

实例

public class ArrayList<E>{
    public boolean add(E e){}
    public E get(int index){}
    //'''
}
//备注:定义的时候使用未知的泛型的变量,使用的时候(创建对象)确定的泛型的具体类型。

定义和使用泛型的方法

修饰符 <代表泛型的变量> 返回值类型 方法名(泛型参数列表){} 
public class GenericDemo{
    //定义有参无返带有泛型的方法
    public <VIP> void show(VIP vip){
        System.out.println(vip);
    }
    //定义含有泛型的有参有返方法
    public <VIP> VIP show2(VIP vip){
        return vip;
    }
}
//测试
public static void main(String[]args){
    //创建对象
    GenericDemo j = new GenericDemo();
    //调用带有泛型的方法
    j.show("欧拉");//VIP vip 参数--->形参  String str = "abc"
    j.show(123);//VIP ---> vip = 123;
    j.show2(3.11);//VIP ---Double vip = 3.14
}

'含有泛型的方法,在调用的时候确定泛型的数据的数据类型
'传递什么类型的参数,泛型就会被解析成什么的类型

定义泛型接口

修饰符 interface 接口名<泛型变量名>{}
//定义格式
public interface Iterable<T> {
    //方法体
    public abstract void add(E e);
}
//使用格式
1.定义实现类时可以直接确定泛型的类型
public class Ouou implements Iterable{
    @Override
    public void add(String s){//...}
}
    //备注:此时泛型【T】的值就是String类型
2.始终不确定泛型的类型,直到创建对象的时候确定泛型的类型
public class <E> Lala  implements Iterable{
    @Override
    public void add(T t){//...}
}

使用泛型需注意

  1. 泛型类如果有多个参数,此时应将多个参数一起放在见括号内。比如<E1,E2,E3>

  2. 泛型类的构造器如下:public GenericClass(){}.

    而下面是错误的:public GenericClass <E>(){}

  3. 实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。

  4. 泛型不同的引用不能相互赋值

    >尽管在编译时ArrayList<String>和ArrayList<Integer>是两种类型,但是,在运行时只有一个ArrayList被加载到JVM中

  5. 泛型如果不指定,将被擦拭,泛型对应的类型均按照Object处理,但不等价于Object。经验:泛型使用一路都用。要不用,一路都不要用。

  6. 如果泛型结构是一个接口或者抽象类,则不可创建泛型类的对象。

  7. jdk1.7,泛型的简化操作:ArrayList< <Fruit> flist = new ArrayList<>();

  8. 泛型的指定中不能使用基本数据类型,可以使用包装类替换。

  9. 在类/接口.上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态
    属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法
    中不能使用类的泛型。

  10. .异常类不能是泛型的

  11. .不能使用new E[]。但是可以: E[] elements = (E[])new Object[capacity];
    参考: ArrayList源码中声明: Object[] elementData,而非泛型参数类型数组。

  12. .父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
    ●子类不保留父类的泛型:按需实现
    ➢没有类型擦除
    ➢具体类型
    ●子类保留父类的泛型:泛型子类
    ➢全部保留
    ➢部分保留

    结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型

泛型的通配符

描述

  • 当使用泛型类或者泛型接口时传递的数据中,泛型的类型不确定,可以使用通配符 <?> 表示。
    一旦程序当中使用泛型通配符后,只能使用Object类中的共性的方法。

通配符的使用

  • 泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用? 。
    ?代表未知的通配符
    此时只能接收数据,不能往集合当中存储数据。
public static void main(Stromg[] args){
    //可以存储整数的集合
    Collection<Integer> list = new ArrayList<>();
    //展示list集合当中的数据
    getElement1(list);
    //可以存储String字符串的集合
    Collection<Integer> list2 = new ArrayList<>();
    getElement2(list2);  '不可以'
    getElement3(list2);  '可以'
}
public static void getElement1(Collection<Integer> call){
   //只能接收Integer类型的数据
}
//public static void getElement2(Collection<Object> call){
//}
public static void getElement3(Collection<?> call){
    //此时?可以代表任意类型
}


//备注:泛型不存在继承关系 Collection<Object> list = new ArrayList<String>(); 这是一种错误的写法。 

泛型的上下限

描述
  • 之前设置泛型的时候,实际上是可以任意设置的。只要是类可以的,但是在java的泛型当中还可以指定一个泛型的上限和下限。
泛型的上限
格式:
	类型名称 <? extends 类名> 对象名
意义:
	只能接收该类型及其子类
    
? extends A:
	G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类
泛型的下限
格式:
    类型名称<? super 类名> 对象名
意义:
    只能接收该类类型及其父类类型
    
? super A:
    G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
示例
  • 比如定义父类Object,String Number Integer 。其中Number类是Integer类的父类
public static void mian(String[] args){
    Collection<Integer> l1=new ArrayList<>();
    Collection<Integer> l2=new ArrayList<>();
    Collection<Integer> l3=new ArrayList<>();
    Collection<Integer> l4=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){//..}
posted @ 2021-07-26 11:42  MikiKawai  阅读(88)  评论(0编辑  收藏  举报