java[学习] 泛型

概念

泛型,即概念参数化类型,将类型由原来的具体的类型参数化,类似方法中的变量参数,此时类型也定义成参数形式(可以称为类型形参),然后再使用调用时传入具体的类型。

##实例##

先来看看Java自带的例子 List

public class Fxing {

    public static void main(String args[]){

        List<String> list = new ArrayList<String>();
        list.add("qqyumidi");
        list.add("corn");

        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i); // 2
            show("name:" + name);
        }
    }


    private static void show(Object object){
        System.out.println(object);
    }
}

上述列子中将lIst的泛型定义为String类型参数,也就是说,相应的List接口中肯定含有类型形参,且get()方法的返回结果也直接是此形参类型。具体看一下list源码

public interface List<E> extends Collection<E> {
    
    int size();

	.......

    E get(int index);

	/**
     * Replaces the element at the specified position in this list with the
     * specified element (optional operation).
     */
    E set(int index, E element);

	/**
     * Inserts the specified element at the specified position in this list
     * (optional operation).  Shifts the element currently at that position
     * (if any) and any subsequent elements to the right (adds one to their
     * indices).
     */
    void add(int index, E element);

    /**
     * Removes the element at the specified position in this list (optional
     * operation).  Shifts any subsequent elements to the left (subtracts one
     * from their indices).  Returns the element that was removed from the
     * list.
     */
    E remove(int index);

	.....

}

我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。

我又写了一个例子

public class Fxing {
    public static void main(String args[]){
        List list = new ArrayList();
        list.add("qqyumidi");
        list.add("corn");
        list.add(100);

        for (int i = 0; i < list.size(); i++) {
            String name = "123";
            if(list.get(i) instanceof  String){
                 name = (String) list.get(i); // 2
            }else if(list.get(i) instanceof Integer){
                name = (list.get(i)).toString(); // 2
            }
            show("name:" + name);
        }
    }	
    private static void show(Object object){
        System.out.println(object);
    }
}

从代码中,可以看出,如果没有定义类型参数,也可以传其他参数,但是在输出的时候就要判断是什么类型,这样就比较麻烦了。

写了一个泛型类

package com.yangyi.javaplan.fxing;

/**
 * Created by GYH on 2017/3/6.
 */
public class Box<T> {

    private T data;

    public Box(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

调用

import java.util.ArrayList;
import java.util.List;

/**
 * Created by GYH on 2017/3/6.
 */
public class Fxing {

    public static void main(String args[]){

        Box<String> stringBox = new Box<String>("guoyuehua");

        show(stringBox.getClass());

        Box<Integer> integerBox = new Box<Integer>(12);

        show(integerBox.getClass());
    }


    private static void show(Object object){
        System.out.println(object);
    }
}

运行结果

class com.yangyi.javaplan.fxing.Box
class com.yangyi.javaplan.fxing.Box
true

从运行结果可以看出,虽然传入了不同的泛型实参类型,但是并没有真正意义上生成不同的类型,传入不同的类型实参,在内存上只有一个,即还是原来的最基本的类型,当然,逻辑上不同的泛型类型。

原因:在Java中的泛型这一概念提出作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件是不包含任何泛型信息的,泛型信息不会进入到运行时阶段。

那么泛型中父子关系的类型吗

栗子

public class Fxing {

    public static void main(String args[]){

        Box<Number> numberBox = new Box<Number>(99);
        Box<Integer> integerBox = new Box<Integer>(12);

        showData(numberBox);
        showData(integerBox);
    }

    private static void showData(Box<Number> box){
       show("name: "+ box.getData());
    }


    private static void show(Object object){
        System.out.println(object);
    }
}

栗子中Number 和 Integer是父子关系,但是编译时报错,…cannot be applied to …,错误,显然在逻辑上Box不能作为Box 的父类,如果非要用,是不是还要判断类型或者强制转换,这就和泛型提出的理论矛盾了,这个时候类型通配符就来了,类型通配符的使用:代替具体的类型实参(是实参、实参、实参 重要的事情说三遍)

栗子

public class Fxing {
    public static void main(String args[]){

        Box<Number> numberBox = new Box<Number>(99);
        Box<Integer> integerBox = new Box<Integer>(12);

        showData(numberBox);
        showData(integerBox);
    }

    private static void showData(Box<?> box){
       show("name: "+ box.getData());
    }

    private static void show(Object object){
        System.out.println(object);
    }
}

还有在使用的时候还要遇到,限制通配符的上限和下限,比如我要限制传的参数必须是Number的子类等等,那么就需要加上限制。

public class Fxing {
    public static void main(String args[]){

        Box<Number> numberBox = new Box<Number>(99);
        Box<Integer> integerBox = new Box<Integer>(12);

        showData(numberBox);
        showData(integerBox);
    }

    private static void showData(Box<? extends Number> box){
       show("name: "+ box.getData());
    }

    private static void show(Object object){
        System.out.println(object);
    }
}

上面定义的是上限,那么下限定义是:Box<? super Number> 形式

注意:并且还要注意的一点是,Java中没有所谓的泛型数组一说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值