JAVA基础: 泛型特点,定义,确定,通配符与边界

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 ;

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、付费专栏及课程。

余额充值