java基础——泛型——20200614-20200615

10 篇文章 0 订阅

尚硅谷_Java零基础教程-java入门必备-初学者基从入门到精通全套完整版(宋红康主讲) P565-576

为什么要有泛型

jdk1.5 以后,开始使用泛型。改写了集合框架中的全部接口和类,为它们增加了泛型支持。

为什么要有泛型?

  1. 解决元素存储的安全性问题,好比商品、药品标签,不会弄错。当没有泛型时,任何类型都可以添加到集合中,类型不安全。
  2. 解决获取数据元素时,需要类型强制转换的问题。还可能有类型转换错误的问题

在集合中使用泛型

  1. 集合接口或集合类在jdk5都修改为带泛型的结构。
  2. 在实例化集合类时,可以指明具体的泛型类型。
  3. 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用指明的类型
  4. 泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,用包装类代替。
  5. 如果实例化时,没有指明泛型的类型,默认是Object

自定义泛型结构

泛型类

  1. 泛型类可能有多个参数,此时应该将多个参数一起放在尖括号内。比如<E1,E2,E3>
  2. 泛型类的构造器如下: publicGenericClass(){}。而这种是错误的:publicGenericClass<E>(){}
  3. 实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。
  4. 泛型不同的引用不能相互赋值。尽管在编译时ArrayList<String>ArrayList<Integer>是两种类型,但是,在运行时只有一个 ArrayList类被加载到JVM中。
  5. 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object。经验:泛型要使用就前后都用。要么,前后都不用。
  6. 如果泛型结构是一个接口或抽象类,则不可创建泛型结构的对象。
  7. jdk1.7,泛型的简化操作:Order<Integer> order = new Order<>();
  8. 泛型的指定中不能使用基本数据类型
  9. 在类/接口 上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参考类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型
  10. 异常类不能是泛型的
  11. 不能使用new E[]。但是可以E[] elements = (E) new Object[capacity]; 参考:ArrayList源码中声明Object[] elementData,而非泛型参数类型数组。
  12. 父类有泛型,子类可以选择保留泛型,也可以选择指定泛型类型。
    子类不保留父类泛型,可以选择没有类型,即擦除;
    也可以指定具体类型。子类还可以部分保留或全部保留。
    子类还可以增加自己的泛型。
class Father<T1,T2>{ }
/*    不保留父类泛型   */
//擦除
class Son1 extends Father{ }
//具体类型
class Son2 extends Father<Integer,String>{ }
/*    保留父类泛型    */
//部分保留
class Son3<T1> extends Father<T1,String>{ }
//全部保留
class Son4<T1,T2> extends Father<T1,T2>{ }

泛型方法

泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有关系。

也就是说,泛型方法所属的类可以是泛型类,也可以不是。

泛型方法可以声明为静态,因为泛型参数是在调用方法时确定的。

public class GenericMethod {

    //泛型方法
    public <T> List<T> copyFromArrayToList(T[] arr){
        List<T> list = Arrays.asList(arr);
        for (T t:list) {
            System.out.println(t);
        }
        return list;
    }
    @Test
    public void test(){
        GenericMethod method = new GenericMethod();
        //泛型方法在调用时,指明泛型参数的类型
        method.copyFromArrayToList(new Integer[]{1,2,3});//  1\n2\n3
        method.copyFromArrayToList(new String[]{"1","2","3"});//  1\n2\n3
    }
}

使用情景

DAO:数据访问对象

定义一个DAO的通用接口,或通用类,使用泛型。class DAO<T>{}
在对应数据库database1的DAO,可以写class DataBase1DAO extends DAO<DataBase1>{}

泛型在继承方面的体现

  • 假设类A是类B的父类
  • G<A>不是G<B>,它们是并列关系
  • A<G>B<G>的父类

通配符的使用 G<?>

G<A>不是G<B>共同的父类是G<?>

List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
//list1 = list;//不行
//list2 = list;//不行
//list.add(1); //不行
list.add(null);

但对于List<?>,里面就不能添加数据了(除了null)。
允许读数据,类型为Object。

 public void print(List<?> list){
        Iterator<?> iterator= list.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
    }

有限制条件的通配符

  • G<? extends A>:可以作为G(A)和G(B)的父类。
  • G<? super A>: 可以作为G(A)和G(B)的子类。
public void test2(){
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;

        List<Student> list3 = null;
        List<Person> list4 = null;
        List<Object> list5 = null;

        list1=list3;
        list1=list4;
        list1=list5;//编译错误
        list2=list3;//编译错误
        list2=list4;
        list2=list5;
		
		//读取数据
        list1 = list4;
        Person person = list1.get(0);

        list2 = list4;
        Object object = list2.get(0);
//        Person person = list2.get(0);//编译错误

        //写入数据
//        list1.add(new Object());//编译错误
        list2.add(new Person());
        list2.add(new Student());
    }

    class Person{ }
    class Student extends Person{}
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值