Java中的泛型和包装类

目录

泛型

包装类


泛型

泛型引入

class Apple{
    public String color;
    public int count;
    public int id = count++;
    public long id(){
        return id;
    }
}

class Orange {}

public class AppleAndOrangeWitnoutGenerics {
    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++) {
           // apples.get(i).id; //会出现语法错误
            ((Apple)apples.get(i)).id();
        }

    }
}

我们会发现,执行以上代码的时候。由于ArrayList保存的是Object,因此可以添加任意对象到容器,无论在编译器还是运行期都不会有问题。在使用ArrayList的get()方法获取对象时,得到的只是Object的引用,必须进行强制类型转换,否则会得到语法错误。在运行时我们试图将Orange对象转型为Apple时,会得到 Exception in thread "main" java.lang.ClassCastException: Orange cannot be cast to Apple这样一个类型转换异常。

使用预定义的泛型可以解决这一问题。如果想要定义Apple对象的ArrayList,可以声明ArrayList<Apple>。尖括号里面是参数类型(可以有多个)。
--这样就可以在编译期防止将错误类型的对象放置到容器中,把运行时的错误变成了编译时期的错误
--取出元素的时候,也不必进行强制类型转换。因为List知道他保存的什么类型,调用get()时自动进行转型。
 

泛型的定义

public class MyArrayList<E> {
    private E[] array;
    ...
}

<>是泛型的标志
E是类型变量,变量名一般要大写
E在定义时是形参,代表 MyArrayList最终传入的类型,现在还不知道

泛型的意义

public class MyArrayList<T> {
    public T[] elem;
    public int usedSize;
    public MyArrayList() {
        //this.elem = new T[10];
        this.elem = (T[])new Object[10]; //注意要这样写
        this.usedSize = 0;
    }
    public void add(T data) {
        this.elem[this.usedSize] = data;
        this.usedSize++;
    }
    public T get() {
        return this.elem[this.usedSize-1];
    }
}

当我们编写这样的代码:

        MyArrayList<String> myArrayList = new MyArrayList<>();
        myArrayList.add("Java"); 
        myArrayList.add(2); //报错
        String ret = myArrayList.get(); //不用进行强转
 

因此泛型的意义:

   1)可以进行自动类型检查
   2)自动进行类型转换

扫描二维码关注公众号,回复: 9031413 查看本文章

3、泛型的几个坑:

1)  泛型类型的参数不能是简单类型。一定要是对象的包装类
   

  MyArrayList<int> myArrayList3 = new MyArrayList<>(); //报错


2)不能够new一个泛型类型的数组

        this.elem = (T[])new Object[10]; //注意要这样写
        T[] elem = new T[10]; //错误


3)泛型类型的参数不参与类型的组成

        MyArrayList<String> myArrayList = new MyArrayList<>();
        System.out.println(myArrayList); //MyArrayList@16d3586

4、泛型是如何编译的:

通过编译器进行类型擦除机制把泛型类转化为非泛型类,(不是替换)编译的时候把尖括号里面的类型擦除为Object类型。泛型只在编译时期才有作用。不必将一些类型转换放到代码中,编译器将进行重要的类型检查。

包装类

1、8种基本数据类型对应的包装类:

除了char --> Character 和 int --> Integer,其他都是首字母大写

2、自动装箱/装包,自动拆箱/拆包:

        //int --> Integer 自动装箱
        Integer a = 10;
        //手动装箱
        Integer b = Integer.valueOf(20);
        System.out.println(b); //20
        //Integer --> int 自动拆箱
        int c = a;
        //手动拆箱 还可以是double ...
        int d = a.intValue();
        System.out.println(b); //10

总结:装箱调用Integer.valueOf()方法(静态的)、拆箱调用Integer.intValue)方法(可变的)

3、辨析Integer:

        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);  //true
        Integer a = 150;
        Integer b = 150;
        System.out.println(a == b); //false

Wow......

Integer是引用类型,等号比较的是地址。在代码中进行了自动装箱的过程,因此调用了valueOf()方法。查看valueOf底层代码:如果一个数的值在-128-127之间,每次去缓存区去取。不在的话,没有都会去new一个新的对象。所以就会存在上面的情况啦。

发布了51 篇原创文章 · 获赞 14 · 访问量 2313

猜你喜欢

转载自blog.csdn.net/qq_41185460/article/details/103448506