当前位置 博文首页 > jcLee95的博客:Java编程基础 - 泛型

    jcLee95的博客:Java编程基础 - 泛型

    作者:[db:作者] 时间:2021-09-18 15:54

    Java编程基础 - 泛型

    【导读】

    . 什么是泛型

    一般传统而言,泛型允许程序员在强类型语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。
    编程技术发展至今很多语言,尤其是强类型语言都有泛型的功能,如Java、C#等。而在弱类型语言却很少出现这样的概念,比如Python就完全没有泛型的概念。
    然而编程技术一天天发展,再区分强弱类型已经完全没有意义,这个概念的区分已经不能向以前那样能帮助我们迅速了解不同编程语言的特点,反而成为了障碍。因为当今弱类型语言也未必没有泛型。举个例子说,2012年微软推出的JavaScript的超集——TypeScript,它广泛吸收了如Java等强类型语言的特点,不仅也有泛型的概念,还充分吸收了其他诸多强类型语言在类型声明与处理上的诸多编程习惯。
    这里推荐阅读另一篇博文:TypeScript泛型。

    泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型

    在使用集合作为容器以前,我们使用数组类容纳元素,数组的缺点是只能存储同类型的元素,并且一旦被初始化长度就不可更改。虽然集合中的一些对象解决了数组中元素单一性和固定性的苦恼,而随着集合的广泛应用我们也遇到一些问题。

    以ArrayList为例,从一段代码说起。
    【例1】

    import java.util.*;
    
    public class WithoutGeneric{
        public static void main(String[] args) {
    
            List list = new ArrayList();
    
            list.add("Python");     // 为该List对象 list 添加几个字符串类型的元素
            list.add("Java");
            list.add("C");
            list.add("C++");
            list.add("C#");
            list.add("JavaScript");
    
            for(int i; i < list.size(); i++){
                String s = list.get(i);
                System.out.println(s);
            } 
        }
    }
    

    Out[]:

    Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
            Type mismatch: cannot convert from Object to String
    
            at WithoutGeneric.main(WithoutGeneric.java:17)
    

    错误提示告诉我们,不能将Object类型转换到Strig。这时因为虽然在代码中我们只往对象list中添加了几个字符串,然而如果我们通过get()方法将其取出时,返回的元素却被同一成了Object类型。即List不能记住其元素的类型,其元素类型都会成为Object类型,以此让List能够容纳各种类型的元素。

    不仅如此,如果只希望list中存放字符串数据,但是不小心向list添加了数字类型的数据,这也是允许的,不会有任何的报错,比如:

    import java.util.*;
    
    public class WithoutGeneric{
        public static void main(String[] args) {
    
            List list = new ArrayList();
    
            list.add("1");
            list.add("2");
            list.add("3");
            list.add(4);
    
            System.out.println(list);
        }
    }
    

    Out[]:

    [1, 2, 3, 4]
    

    代码正确,并且输出时你完全看不出元素的类型不一样。(作为比较,Python中没有泛型但可以看出,因为Python中print的结果是['1','2','3',4])。

    种种原因,泛型应运而生。有了泛型以后,我们的代码写成这样:

    import java.util.*;
    
    public class WithoutGeneric{
        public static void main(String[] args) {
            // 使用泛型,也就是在菱形中规定了其元素的类型。
            List<String> list = new ArrayList<>();
    
            list.add("Python");     // 为该List对象 list 添加几个字符串类型的元素
            list.add("Java");
            list.add("C");
            list.add("C++");
            list.add("C#");
            list.add("JavaScript");
    
            for(int i=0; i < list.size(); i++){
                
                String s = list.get(i);
                System.out.println(s);
            } 
        }
    }
    

    Out[]:

    Python
    Java
    C
    C++
    C#
    JavaScript
    

    同时你也不需要再担心是否不小心加入了其他的类型,比如在上面代码中,添加一条语句:

    list.add(1);
    

    将引发如下错误:

    Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
            The method add(int, String) in the type List<String> is not applicable for the arguments (int)
    
            at WithoutGeneric.main(WithoutGeneric.java:15)
    

    这就是泛型。到这里我们提出几个问题:

    • 是否是由集合类才支持泛型,如果不是那哪些类支持呢?
      答:并不是集合类才支持泛型,所有的类甚至自定义类都可能能够支持泛型。
    • 支持泛型的条件是什么呢?
      答:在定义类或者方法时,用泛型定义的菱形语法(一对尖括号<>)定义了一个或者多个类型形参。

    .

    cs