美文网首页
Java泛型

Java泛型

作者: 燕城白夜 | 来源:发表于2019-08-26 08:34 被阅读0次

Java 1.5版本中增加了泛型。

为什么需要引入泛型?
在引入泛型之前,读取集合中的每一个元素都需要进行转换,如果在集合中插入了错误类型的对象,那么就会在程序运行时报类型转换的错误。在引入泛型后我们可以告诉编译器需要向集合中插入的元素类型,编译器会在插入元素时进行自动转换,并在编译时报告往集合中插入错误类型的代码。

在Java代码中还可以继续使用原生态类型例如List等的原因是因为向后兼容,让以前未使用泛型的代码保存合法,并且能够与使用泛型的代码进行交互。在新代码中不推荐使用List等原生态类型。
List 和 List<Object> 区别?
两种集合都允许插入任何类型的对象。简单说List逃避了编译器的类型检查,而List<Object>则明确告知编译器其可以保存任何类型的对象。

泛型有子类型化的规则,List<String> 是原生态类型List的子类型而不是List<Object>的子类型,所有可以将List<String> 类型的对象传递给List类型的参数但不能传递给List<Object>类型的参数:
package template;

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

/**
* @author: zhouzhaoping
* @description:
* @date: 2019-08-25
*/
public class Test1 {

  public static void main(String[] args) {
      List<String> list = new ArrayList<String>();
      list.add("1");
      list.add("2");
      list.add("3");
      list.add("4");
      list.add("5");
      test1(list);
      test2(list); // 报错
  }

  public static void test1(List list) {
      for (Object o : list) {
          System.out.println("test1:" + o.toString());
      }
  }

  public static void test2(List<Object> list) {
      for (Object o : list) {
          System.out.println("test2:" + o.toString());
      }
  }

}

使用原生态类型List会失去类型安全性,使用List<Object>这样的参数化类型则不会,为了更好的说明请参考下面的代码。

public static void main(String[] args) {
      List<String> strings = new ArrayList<String>();
      unsafeAdd(strings, new Integer(42));
      String s = strings.get(0);

  }

  private static void unsafeAdd(List list, Object o) {
      list.add(o);
  }

在最新的Java8中,上述的代码已经无法通过编译。
将List替换为List<Object>能看到更明确的报错信息。

在不确定集合元素类型的情况下使用无限制的通配符类型代替使用原生态类型

如果你需要筛选集合的交集,使用原生态类型你可以这样写:

public static int numElementsInCommon(Set s1, Set s2) {
      int result = 0;
      for (Object o1: s1) {
          if (s2.contains(o1)) {
              result++;
          }
      }
      return result;
  }

由于使用了原生类型,这样写是很危险的。
如果要定义一个参数化的类型(例如List<String>,因为不能使用List<E>定义),但不确定或不关心实际的参数类型则可以使用一个?来代替。

public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        return result;
    }

可以将任何元素放入原生态类型的集合中,因此很容易破坏该集合的类型约束条件,例如如下代码可通过编译:

public static int numElementsInCommon(Set s1, Set s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        s1.add("1");
        s2.add(2);
        return result;
    }

但如下代码却不行:

public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        s1.add("1");
        s2.add(2);
        return result;
    }

通过以上例子不难看出?通配符主要使用在函数的形参上且在该函数内部不会修改该集合的场景中。

数组与泛型

数组与泛型相比有两个重要的不同点,第一个是数组是协变的而泛型不是,例如如果Sub是Super的子类型,那么Sub[]也是Super[]的子类型。相反泛型则是不可变的:对于任意两个不同的类型Type1和Type2,List<Type1>和List<Type2>没有关系( 其实这是数组设计的缺陷而不是泛型)。
这个不同导致使用泛型可以比使用数组更容易发现错误,参考如下的代码:

public static void main(String[] args) {
        Object[] objectArray = new Long[1];
        objectArray[0] = "I don't fit in.";

    }

这段代码可以通过编译但在执行时会抛出异常。

public static void main(String[] args) {
        List<Object> o1 = new ArrayList<Long>();
        o1.add("I don't fit in.");
    }

而这段代码则无法通过编译,对比数组我们可以更早的发现错误。

相关文章

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • 第二十八课:泛型

    泛型出现之前 泛型出现之后 Java深度历险(五)——Java泛型

  • Kotlin 泛型

    说起 kotlin 的泛型,就离不开 java 的泛型,首先来看下 java 的泛型,当然比较熟悉 java 泛型...

  • java泛型中类型擦除的一些思考

    java泛型 java泛型介绍 java泛型的参数只可以代表类,不能代表个别对象。由于java泛型的类型参数之实际...

  • Java泛型

    参考:Java知识点总结(Java泛型) 自定义泛型类 自定义泛型接口 非泛型类中定义泛型方法 继承泛型类 通配符...

  • Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型

    Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型 在代码进入和离开的边界处,会处理泛型 Java泛型作...

  • JAVA 核心笔记 || [xxx] 泛型

    泛型 JAVA 的参数化类型 称为 泛型 泛型类的设计 Learn12.java 运行

  • 简单回顾Java泛型之-入门介绍

    什么时候开始有了Java泛型?什么是Java泛型?为什么要引入Java泛型?什么时候用到了泛型?可不可以给泛型下一...

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

  • JAVA-泛型

    JAVA-泛型 sschrodinger 2018/11/15 简介 泛型是Java SE 1.5的新特性,泛型的...

网友评论

      本文标题:Java泛型

      本文链接:https://www.haomeiwen.com/subject/hwkkectx.html