泛型的详解

1. 装箱/装包,拆箱/拆包:

什么是装箱/装包:将基本数据类型变成包装类类型的过程叫做装箱/装包。

什么是拆箱/拆包:将包装类类型变成基本数据类型的过程叫做拆箱/拆包。

装箱和拆箱又有两个方法,分别是显示和自动。

显示就是我们自己调用valueOf方法,自动就是底层帮我们调用。

public class Test {
    public static void main(String[] args) {
        // 拆箱/拆包
        Integer a = 10;
        int b = a.intValue();//显示拆箱
        int c = a;//自动拆箱
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);

        // 装箱/装包
        int e = 5;
        Integer f = e;//自动装箱
        Integer g = Integer.valueOf(e);//显示装箱
        System.out.println(e);
        System.out.println(f);
        System.out.println(g);
    }
}

思考:下面代码的运行结果是什么?

public class Test {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);

        Integer c = 200;
        Integer d = 200;
        System.out.println(c == d);
    }
}

答案:true
           false

讲解:

上面的代码是一个装箱的过程,我们可以去观察Integer.valueOf()的源代码:

@IntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

 观察发现,如果传入的值在一个范围内,就返回某个数组中的元素,否则就会返回一个新的对象。而IntegerCache.low的值是-128,IntegerCache.high的值是127,意思就是当传入的参数不在 这个范围的时候,valueOf返回的就是一个新的对象。

具体原因:

存在一个缓冲数组,当传入的数值在一个范围的时候是去数组直接拿值,不在这个范围时,返回的是新对象。

以此类推,可以调用一下其他包装类的valueOf方法,最终结论如下:

2. 什么是泛型?

顾名思义,所谓泛型就是指能存放所有类型数据的类型,我们肯定会想到用Object,那我们就拿它试试。

import java.util.Arrays;
class MyArray{
    private Object[] po = new Object[10];

    public Object getPo(int pos) {
        return po[pos];
    }

    public void setPo(int pos, Object po) {
        this.po[pos] = po;
    }

    @Override
    public String toString() {
        return "MyArray{" +
                "po=" + Arrays.toString(po) +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setPo(0, 1);
        myArray.setPo(1, "hello");
        System.out.println(myArray);
        String s = (String) myArray.getPo(1);
        System.out.println(s);
    }
}

这么写有两个明显的缺点:

1. 存放数据太乱,什么都能放;

2. 每次取出数据的时候还需要强转。 

Java就为我提供了更为便捷的一个方法:

class MyArray<E>{
    private Object[] po = new Object[10];

    public E getPo(int pos) {
        return (E)po[pos];
    }

    public void setPo(int pos, E po) {
        this.po[pos] = po;
    }

    @Override
    public String toString() {
        return "MyArray{" +
                "po=" + Arrays.toString(po) +
                '}';
    }
}

当我们存放的数据类型与<>中的类型不一样时,他就会自动检查数据类型,这样一来我们在存放数据时就不会很乱。,并且在我们获取里面的内容时也不需要强制类型转化,非常的便捷。

 注意:

1. <>里面只能写类类型,不能写简单类型;

2. 当我们创建泛型对象时也可以不加<>,因为泛型是在JDK5引入的,这样是为了兼容以前的版本,所以不会报错,这种不加<>的也叫做裸类型。

3. 泛型是怎么进行编译的?(擦除机制)

泛型是编译时期的一种机制,在运行时没有泛型的概念【JVM中没有泛型的概念】。

在编译完成后,类型形参列表都会被擦除为Object。

此时<>当中的内容不参与类型的组成。

 

4. 泛型的上界:

class MyArray<E extends Number>{};

只接受Number的子类型作为类型实参,使用其他类型时会报编译错误。

C是A的子类,B不是A的子类,编译报错:

如果有多个上界,则需要“&”连接:

public class MyArray <E extends A & Comparable<E>>

 若有多个上界,则类型参数必须是所有上界的子类。

例:

MyArray类:
public class MyArray <E extends A & Comparable<E>>{
    Object[] myArray = new Object[2];

    @Override
    public String toString() {
        return "MyArray{" +
                "myArray=" + Arrays.toString(myArray) +
                '}';
    }
}

A类:

public class A {
}

C类:

public class C extends A implements Comparable<C>{
    int anInt;
    int next;

    public C(int anInt, int next) {
        this.anInt = anInt;
        this.next = next;
    }

    @Override
    public int compareTo(C o) {
        return o.anInt - this.anInt;
    }

    @Override
    public String toString() {
        return "C{" +
                "anInt=" + anInt +
                ", next=" + next +
                '}';
    }
}

 

5.泛型方法:

我们可以不写泛型类,直接在普通类里写泛型方法,例:

public class Test {
//静态的泛型方法 需要在static后用<>声明泛型类型参数
    public static <E> void mySwap(E[] array, int i, int j) {
        E t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
    public static void main(String[] args) {
        Integer[] array = new Integer[]{1, 2};
        mySwap(array, 0, 1);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值