Java入门:15.泛型特点,定义,确定,通配符与边界,链表容器封装设计-001

1 泛型

1.1 泛型特点

  • 泛型使用主要是在定义类或定义方法时,如果类中(方法中)有一些内容的类型不确定,可以声明一个泛型来暂时代替这些类型

  • 一般在类或方法使用时,可以确定泛型的类型

  • 泛型的作用

    1. 设计时,通过使用泛型,可以体现我们对程序整体业务结构的把控。

    2. 编译时,可以对泛型类型提前做检查,避免程序运行时出现的类型转换问题(下转型问题)

      例如:有一个容器,如果没有泛型,容易中所有跟元素相关的类型都是Object

      如果逻辑上需要容器存入User,语法上可以存储一个Car

      基于逻辑在使用容器中的元素时,都会先将其下转型成User在操作

      此时当遇见Car类型的元素就会报错

      有了泛型后,可以在使用容器时,通过泛型指定容器中只能存储User

      如果偷偷存了一个Car,编译时就会报错

    3. 编码时,可以省略下转型代码

  • 泛型的使用分为2部分

    1. 泛型的定义

    2. 泛型的确定

扩展:泛型擦除

  • 泛型的作用只在编译时生效

  • 一旦编译完成,虚拟机运行时,就没有泛型这个内容了

  • 所有用泛型表示的类型都是Object

1.2 泛型定义

  • 在定义类的时候, 类中有些内容的类型不确定,可以声明一个泛型来表示

    这些不确定的类型一定是相同类型

    class A<T>{
       T a ;
       T b ;
        public T t1(T i){
            
        }
        
        public int t2(String s){}
    }

  • 在定义的类时候,如果类的内容中有多种类型不确定,我们可以声明多个泛型

    class A<T1,T2>{
        T1 a ;
        T2 b ;
        public T2 t1(T1 i)
    }
  • 在定义方法时(以static方法偏多),如果方法中有些内容的类型不确定,可以为其声明泛型

    也可以声明多个泛型

    一般多用于静态方法的参数类型不确定

    public  <T>  T t1(T a , T b){}

1.3 确定泛型

  • 在使用泛型类或泛型方法时,来确定泛型代表的具体类型

确定类泛型

class A<T>{
    T i ;
    public A(T i){
        this.i = i ;
    }
}
​
A<String> a ; //定义变量(成员变量,局部变量,参数变量)
              //类A中的i属性是String类型的
​
new A<String>();//创建对象
​
class B extends A<String>{}  //继承父类
class B implements A<String>{} //实现接口

确定方法泛型

//泛型方法
public static <T> T t1(T a){}
​
​
//对于方法的使用,就一种情况,调用方法
//泛型方法中的泛型类型,需要在调用方法时确定,怎么确定呢?
//默认就是传递参数的类型
t1("zs") ;// a参数是String类型, T泛型就是String类型
t1(user) ;//a参数是User类型,T泛型就是User类型
​


确定多个泛型

class A<T1,T2>{
    T1 i ;
    T2 j ;
}
​
​
A<String,User> a ;

同时定义和确定泛型

interface Box<E>{
    void add(E e);
}
​
​
class ArrayBox<T> implements Box<T>{
    //ArrayBox是一个具体的容器,可以存储一组元素
    //但定义ArrayBox类的时候,不确定存储的元素是什么类型的?
    //可以声明一个泛型来表示
    
    T[] objects ;
    
    public void add (T t){}
    
}

1.4 泛型通配符

  • 在本应确定泛型的时候,却无法确定泛型,可以使用?通配符代替,表示什么类型都行,目的是让编译通过

    // 定义泛型
    class A<T>{
        T i ;
    }
    ​
    ​
    //情况一
    class B{
        A<Object> a ;  //此时传递确定了具体泛型的属性值,就报错
                       //a = new A<String>(); 
                       //如何避免错误 用?代替Object A<?> a ;
    }
    ​
    B b = new B();
    b.a = new A<String>();
    b.a = new A<User>();
    ​
    ​
    //情况二
    class B{
        //方法中有一个A类型的参数,在定义这个参数时,不确定A中的泛型T
        //调用方法传递参数时,再确定类型
        //此时传递的参数a如果确定了具体的泛型,就会报错
        //t1(new A<String>())
        //使用?代替Object  t1(A<?> a)
        public void t1(A<Object> a){
            
        }
    }
    ​
    t1(new A<String>());
    t1(new A<User>())
    ​

注意:不能带泛型强转

class A<T>{
    T i ;
}
​
A<Object> a = new A<Object>();
a.i = "zs" ;
Object o = a ;
....
A<String> b = (A<String>)a ;  //错误
A<Object> c = (A<Object>)o ;
Object[] os  = new Object[]{"a","b","c"};
String[] ss = (String[])os ; //错误

1.5 泛型的边界

  • 基于通配符?使用的情况下

  • ?使用的情况是:应该确定泛型了,但依然无法确定

  • 边界的特点是:虽然无法确定具体的泛型,但能确定泛型的一个范围(边界)

    class A extends Object{}
    class B extends A{}
    class C extends D{}
    ​
    ​
    class X<T>{
        T i ;
    }
    ​
    class Y{
        X<?> x1 ; //x1 = new X<String>() , x1 = new X<User>();
        X<? extends A> x2 ;//x的泛型必须是A或A的子类
                           //x2 = new X<A>();   x2 = new X<B>();
                           //x2 = new X<String>(); 错误
        X<? super B> x3 ; //x的泛型必须是B或B的父类
                          //x3 = new X<A>() , x3 = new X<B>(),x3 = new X<Object>
                          //x3 = new X<String>(). x3 = new X<C>()   错误
    }
    ​
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值