概述

说起类型安全的容器,那么什么是类型不安全的容器呢?容器用来存储数据,常见的存储数据的容器有数组和集合,数组有以下特点:

  • 长度固定

  • 只能存储同一种类型的数据

因为数组只能存储同一种数据类型的数据,那么它就是类型安全的容器,因为集合可以存储任意类型的数据,比如我可以在List中存储一个Apple、一个Orange,但是在取的时候我不知道它们是什么,只知道它们是Object,这样,我以为取出来的是Apple,但是取出来了一个Orange,我又想要用Apple的种子种苹果,但是涨出来发现时橘子。

实例

类型不安全的容器

class Apple{
    private static long counter;
    private final long id = counter++;
    public long id(){
        return id;
    }
}

class Orange{

}


public class ApplesAndOrangesWithoutGenerics {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        ArrayList apples = new ArrayList();
        for(int i = 0; i<3; i++){
            apples.add(new Apple());
        }

        apples.add(new Orange());

        for (int i = 0; i<apples.size(); i++)
            ((Apple)apples.get(i)).id();
    }
}
  • @SuppressWarnings:不受检查的异常,也就是可以抑制警告信息

  • 存储进去三个Apple对象和一个Orangle对象

  • 想取出Orange的id属性

  • 出现运行时异常ClassCastException: net.sailfishc.holding.Orange cannot be cast to net.sailfishc.holding.Apple

类型安全的容器(泛型)

class Apple{
    private static long counter;
    private final long id = counter++;
    public long id(){
        return id;
    }
}

class Orange{

}


public class ApplesAndOrangesWithoutGenerics {
   
    public static void main(String[] args) {
        ArrayList<Apple> apples = new ArrayList<Apple>();
        for(int i = 0; i<3; i++){
            apples.add(new Apple());
        }

        // apples.add(new Orange());

        for (int i = 0; i<apples.size(); i++)
            apples.get(i).id(); //不用强制转换
    }
}
  • 在创建List的时候加入了泛型,使其只能放入Apple

  • 在试图加入Orange的时候会出现编译器异常

  • 在取对象的时候不需要强制转换为Apple,因为编译器已经知道存储的是Apple

向上转型使用泛型

明确指定某个类型作为泛型参数的时候,并不仅限于将该对象放置到容器中,向上转型也可以像其他类型一样作用于泛型。

class GrannySmith extends Apple{}
class Gala extends Apple{}
class Fuji extends Apple{}
class Braeburn extends Apple{}

public class GenericsAndUpcasting {
    public static void main(String[] args) {
        ArrayList<Apple> apples = new ArrayList<Apple>();
        apples.add(new Gala());
        apples.add(new GrannySmith());
        apples.add(new Fuji());
        apples.add(new Braeburn());
        for (Apple apple : apples) {
            System.out.println(apple);
        }

        List<Apple> list1 = new ArrayList<Apple>();
        List<Apple> list2 = new LinkedList<Apple>();
    }
}
  • Apple

    • GrannySmith

    • Gala

    • Fuji

    • Braeburn

  • 层次结构如上所示,Apple的子类都可以作为集合的元素加入到集合中,并且不会有任何影响。

在实际编码中一般都建议使用类型安全的容器,这样不容易出错,出错也会在编译期间就会展现出来。


sailfishc
47 声望9 粉丝

喜欢孤独与自由