• 什么是泛型。

      • Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当“可变数组”。

        public class ArrayList {
        private Object[] array;
        private int size;
        public void add(Object e) {...}
        public void remove(int index) {...}
        public Object get(int index) {...}
        }
      • 如果用上述ArrayList存储String类型,会有这么几个缺点:

        • 需要强制转型;

        • 不方便,易出错。

        • 代码必须这么写:
          ArrayList list = new ArrayList();
          list.add("Hello");
          // 获取到Object,必须强制转型为String:
          String first = (String) list.get(0);

          很容易出现ClassCastException,因为容易“误转型”。

          list.add(new Integer(123));
          // ERROR: ClassCastException:
          String second = (String) list.get(1);

          要解决上述问题,我们可以为String单独编写一种ArrayList。

          public class StringArrayList {
          private String[] array;
          private int size;
          public void add(String e) {...}
          public void remove(int index) {...}
          public String get(int index) {...}
          }

          这样一来,存入的必须是String,取出的也一定是String,不需要强制转型,因为编译器会强制检查放入的类型。

          StringArrayList list = new StringArrayList();
          list.add("Hello");
          String first = list.get(0);
          // 编译错误: 不允许放入非String类型:
          list.add(new Integer(123));

          问题暂时解决。然而,新的问题是,如果要存储Integer,还需要为Integer单独编写一种ArrayList。实际上,还需要为其他所有class单独编写一种ArrayList。

          这是不可能的,JDK的class就有上千个,而且它还不知道其他人编写的class。

          为了解决新的问题,我们必须把ArrayList变成一种模板:ArrayList<T>

          public class ArrayList<T> {
          private T[] array;
          private int size;
          public void add(T e) {...}
          public void remove(int index) {...}
          public T get(int index) {...}
          }

          T可以是任何class。这样一来,我们就实现了:编写一次模版,可以创建任意类型的ArrayList。

          // 创建可以存储String的ArrayList:
          ArrayList<String> strList = new ArrayList<String>();
          // 创建可以存储Float的ArrayList:
          ArrayList<Float> floatList = new ArrayList<Float>();
          // 创建可以存储Person的ArrayList:
          ArrayList<Person> personList = new ArrayList<Person>();

          这样一来,既实现了编写一次,万能匹配,又通过编译器保证了类型安全:这就是泛型。

    向上转型

      • 在Java标准库中的ArrayList<T>实现了List<T>接口,它可以向上转型为List<T>。

        public class ArrayList<T> implements List<T> {
        ...
        } List<String> list = new ArrayList<String>();

        类型ArrayList<T>可以向上转型为List<T>。不能把ArrayList<Integer>向上转型为ArrayList<Number>List<Number>。ArrayList<Integer>和ArrayList<Number>两者完全没有继承关系。

  • 使用泛型

    • 使用ArrayList时,如果不定义泛型类型时,泛型类型实际上就是Object

    • 编译器如果能自动推断出泛型类型,就可以省略后面的泛型类型。

      // 可以省略后面的Number,编译器可以自动推断泛型类型:
      List<Number> list = new ArrayList<>();
    • 泛型接口

      • 除了ArrayList<T>使用了泛型,还可以在接口中使用泛型。例如,Arrays.sort(Object[])可以对任意数组进行排序,但待排序的元素必须实现Comparable<T>这个泛型接口。

        public interface Comparable<T> {
        /**
        * 返回负数: 当前实例比参数o小
        * 返回0: 当前实例与参数o相等
        * 返回正数: 当前实例比参数o大
        */
        int compareTo(T o);
        }

        可以直接对String数组进行排序。

        // sort
        import java.util.Arrays; public class Main {
        public static void main(String[] args) {
        String[] ss = new String[] { "Orange", "Apple", "Pear" };
        Arrays.sort(ss);
        System.out.println(Arrays.toString(ss));
        }
        }

        这是因为String本身已经实现了Comparable<String>接口。如果换成我们自定义的Person类型试试。

         1 // sort
        2 import java.util.Arrays;
        3
        4 public class Main {
        5 public static void main(String[] args) {
        6 Person[] ps = new Person[] {
        7 new Person("Bob", 61),
        8 new Person("Alice", 88),
        9 new Person("Lily", 75),
        10 };
        11 Arrays.sort(ps);
        12 System.out.println(Arrays.toString(ps));
        13
        14 }
        15 }
        16
        17 class Person {
        18 String name;
        19 int score;
        20 Person(String name, int score) {
        21 this.name = name;
        22 this.score = score;
        23 }
        24 public String toString() {
        25 return this.name + "," + this.score;
        26 }
        27 }

        运行程序,我们会得到ClassCastException,即无法将Person转型为Comparable。我们修改代码,让Person实现Comparable<T>接口。

         1 // sort
        2 import java.util.Arrays;
        3
        4 public class Main {
        5 public static void main(String[] args) {
        6 Person[] ps = new Person[] {
        7 new Person("Bob", 61),
        8 new Person("Alice", 88),
        9 new Person("Lily", 75),
        10 };
        11 Arrays.sort(ps);
        12 System.out.println(Arrays.toString(ps));
        13 }
        14 }
        15 class Person implements Comparable<Person> {
        16 String name;
        17 int score;
        18 Person(String name, int score) {
        19 this.name = name;
        20 this.score = score;
        21 }
        22 public int compareTo(Person other) {
        23 return this.name.compareTo(other.name);
        24 }
        25 public String toString() {
        26 return this.name + "," + this.score;
        27 }
        28 }

        运行上述代码,可以正确实现按name进行排序。

      

                                      未完待续

Java学习_泛型的更多相关文章

  1. Java学习之——泛型

    1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfac ...

  2. 黑马程序员:Java编程_泛型

    =========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中.使用 ...

  3. 5 Java学习之 泛型

    1. 基本概念          泛型是Java SE 1.5的新特性,泛型的本质是 参数化类型 ,也就是说所操作的 数据类型 被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为 ...

  4. Java学习笔记--泛型

    一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...

  5. Java学习笔记——泛型

    假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...

  6. Java学习点滴——泛型

    基于<Java编程思想>第四版 前言 虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的. 语法 Java只需要一个<>就可定义泛型.在<> ...

  7. JAVA学习之泛型

    ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:1.整个ArrayList<E>称为泛型类型 2.ArrayList< ...

  8. Java学习之泛型和异常

    泛型 1,设计原则或目的:只要代码在编译的时候没有错误,就不会抛异常.  2,泛型通配符  :类型通配符一般是使用 ? 代替具体的类型实参.注意了,此处是类型实参,而不是类型形参!相当于(父类作用)L ...

  9. Java学习之==>泛型

    一.什么是泛型 泛型,即“参数化类型”,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型.也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类.接口 ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:QListWidgetItem的构造方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QListWidgetItem对象专门用于作为QListWidget对象的一个项. QListWid ...

  2. PHP代码审计分段讲解(5)

    11 sql闭合绕过 源代码为 <?php if($_POST[user] && $_POST[pass]) { $conn = mysql_connect("**** ...

  3. Day6【Scrum 冲刺博客】

    每日会议总结 昨天已完成的工作 方晓莹(PIPIYing) 对接住户相关接口 处理token过期重定向.页面跳转.错误状态处理等内容 方子茵(Laa-L) 暂无 黄芯悦(Sheaxx) 完善物业报修页 ...

  4. 网络QoS的平衡之道——音视频弱网对抗策略介绍

    作者:网易智企云信资深音视频引擎开发工程师 王兴鹤 随着AI和5G的到来,音视频应用将变得越来越广泛,人们对音视频的品质需求也越来越高,视频分辨率已经从高清发展为超高清.VR,视频帧率也已出现60fp ...

  5. 威联通(NAS)搭建个人音乐中心

    我为什么要自己搭建音乐服务 曾记得早些年,音乐是可以随便在线听,随便下载的,没有付费这么一说的(背后是音乐平台提供的版权支持).我们听音乐也就可以很随意,但是这几年,音乐的版权开始管理的严禁,音乐没地 ...

  6. 初中的一些OI琐屑 & APIO2020 & NOI2020

    这篇文章会发布在我的博客上 https://www.cnblogs.com/dmoransky/(一个小习惯,把信息学竞赛的学习历程记录在个人博客中). 借这篇随笔回顾并简短总结一下我的初中OI(信息 ...

  7. C++ 虚函数表与多态 —— 关键字 override 的用法

    override 仅能用于虚函数,他属于C++新特性,是重写覆盖的意思,他的存在仅仅是为了提高代码的可阅读性: 作用: 1. 提示程序的阅读者,这个函数是重写父类的功能. 2. 防止程序员在重写父类的 ...

  8. react第七单元(组件的高级用法-组件的组合(children的用法)-高阶组件-封装组件)

    第七单元(组件的高级用法-组件的组合(children的用法)-高阶组件-封装组件) #受控组件 简而言之,就是受到状态state控制的表单,表单的值改变则state值也改变,受控组件必须要搭配onc ...

  9. vue第十五单元(熟练使用vue-router插件)

    第十五单元(熟练使用vue-router插件) #课程目标 1.掌握路由嵌套 2.掌握导航守卫 #知识点 #一.路由嵌套 很多时候,我们会在一个视口中实现局部页面的切换.这时候就需要到了嵌套路由. 也 ...

  10. 用DirectX 11绘制一个Cube

    之前一篇文章讲了如何初始化DirectX 11,现在在此基础上绘制一个Cube,总体可概括为以下几个步骤: 定义Cube顶点数据结构 创建Vertex Buffer和Index Buffer 编写应用 ...