浅谈java泛型

引言

前面我们说到了集合,但是集合有个缺点——把一个对象“丢进”集合里后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型。但这样会带来如下两个问题:

  1. 集合对元素类型没有任何限制,可能把不同元素对象放进去,将会引发异常。

  2. 取元素后要进行强制类型转换,可能引发ClassCastException异常。


什么是java泛型?

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,主要目的是建立具有类型的安全的集合框架。

泛型的定义与使用

泛型类

(此处用一个完整例子来展示)

//在实例化泛型类时,必须指定T的具体类型
public class Person<T> {
    //成员变量类型T均由外部指定
    private T name;
    private T age;
    private T sex;

    public Person(T name, T age, T sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name=" + name +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }

    public static void main(String args[]) {
        //若不传入泛型参数类型,参数可以为任意类型,此时name为String,age为int,sex为String
        Person p = new Person("张三", 20, "男");
        //此时name为String,age为double,sex为boolean
        Person p2 = new Person("李四", 21.5, false);
        //指定T类型为String后,此时若传入参数为("王五", 22, "男")将发生编译错误,age也必须为String类型
        Person<String> p3 = new Person<>("王五", "22", "男");
        System.out.println(p);
        System.out.println(p2);
        System.out.println(p3);
    }
}

运行结果,注意看参数类型:


泛型接口

以下为JDK5.0集合框架中Map接口定义的一部分:

publicinterface Map<K, V> {

publicvoid put(K key, V value);

public Vget(K key);

}

后文将以Map接口的实现类来进行讲述

集合泛型类

注意:当声明或实例化一个泛型对象时,必须指定类型参数的值

如:Map<String, String> map = newHashMap<String, String>();

参数类型可以是:基本数据类型的装箱类、引用类型

对于常见的泛型模式,推荐的名称是:

K ——键,比如映射的键。

V ——值,比如 List 和 Set 的内容,或者 Map 中的值。

E ——异常类。

T ——泛型。

示例如下:(学生类是个基本的JavaBean,有name.age.sex属性以及构造方法,代码省略)

@Test
public void genericTest(){
    Map<String,Student> student=new HashMap<>();
    Student stu1=new Student("赵一",23,"男");
    Student stu2=new Student("小芳",21,"女");
    student.put("坏学生",stu1);
    student.put("好学生",stu2);
    Iterator it=student.entrySet().iterator();
    while(it.hasNext()){
        Map.Entry entry= (Map.Entry) it.next();
        Object key=entry.getKey();
        Student s= (Student) entry.getValue();
        System.out.println(key+"----"+s.getName()+"----他/她的年纪是:"+s.getAge());
    }
}

运行结果:

泛型通配符

首先做个小测试:

List<String> slist=new ArrayList<>();
List<Integer> ilist=new ArrayList<>();
System.out.println(slist.getClass()+"?="+ilist.getClass());

结果:


由此我们可以知道List<String>和List<Integer>的类型相同,即泛型类型在逻辑上可以看做是多个不同的类型,实际上都是相同的基本类型。

因此,形如Generic<Animal>和Generic<Dog>不是具有父子关系的泛型类型,所以我们需要一个逻辑上可以表示同时是Generic<Animal>和Generic<Dog>父类的引用类型,通配符由此而来。

类型通配符一般是用?代替具体的类型实参。当具体类型不确定时,可用?通配符来表示位置类型,如:

Class<?> classType=Class.forName(“java.lang.String”);


通配符上下边界

List<? extends Number>list;表示通配符的上边界,即?只能被赋值为Number或其子类型。

List<? super Integer>list;表示通配符的下边界,即?只能被赋值为Integer或其父类型。

关于<T>和<?>

Class<T>在实例化的时候,T要替换成具体类。

Class<?>时个通配泛型,?可以带便任何类型,主要用于声明时的限制情况。

 我觉得<T>和<?>还有更多值得思考的地方,比如我之前一直在想的一个问题,T泛型其实本来就可以代表任意类型(任意基本数据类型的包装类)了,只是在实例化的时候替换成具体类,那么?通配符与之相比就作用来说又有什么区别呢?

由于编者水平有限…待更加深入学习后再做解释。


本文参考: java泛型详解java泛型详解-最详细
原文出自:https://my.csdn.net/qq_37094660(如需转载请注明出处)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值