Java核心技术知识点笔记—泛型程序设计

Posted lykAnd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java核心技术知识点笔记—泛型程序设计相关的知识,希望对你有一定的参考价值。

1、泛型方法:

(1)定义:泛型方法的定义方式,将类型变量放在修饰符的后面,返回类型的前面。

public class TestGenericC 

    public <T> void test(T t) 
        System.out.print(t);
    

如上,在一个普通类中定义了一个泛型方法。

(2) 调用:当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型:

public class Main 
    public static void main(String[] args) 
        TestGenericC genericC = new TestGenericC();
        genericC.<String>test("generic test");
    

大多数情况下,尖括号中的类型参数可以省略,编译器有足够的信息能够推断出所调用的方法。(如上例,编译器使用names的类型(即String[])与泛型类型T[]进行匹配并推断出T一定是String。)

2、泛型代码和虚拟机

虚拟机没有泛型类型对象:所有对象都属于普通类。

2.1、类型擦除:定义一个泛型类型都自动提供了一个相应的原始类型(raw type)。原始类型的名字就是删去类型参数后的泛型类型名。擦除(erased)类型变量,并替换为限定类型(无限定的用Object替换)。

public class TestGenericC<T>  //泛型类型
    private T first;
    private T second;


public class TestGenericC //原始类型
    private Object first;
    private Object second;

如上所示,TestGenericC的泛型类型T没有限定,因此它的原始类型用Object来替换。如果对T有所限定,则使用第一个限定的类型变量来替换。如:

public class TestGenericC<T extends Comparable & Serializable>  //泛型类型
    private T first;
    private T second;


public class TestGenericC //原始类型
    private Comparable first;
    private Comparable second;

对类型T做了限定,原始类型中使用第一个限定类型Conparable来进行替换。为了提高效率,应该将标签(tagging)接口(没有方法的接口)放在边界列表的末尾。

2.2、翻译泛型表达式:当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。例如:

public class TestGenericC<T>  //泛型类型
    private T first;

    public T getFirst() 
        return first;
    


public class Main 
    public static void main(String[] args) 
        TestGenericC<String> genericC = new TestGenericC();
        String first = genericC.getFirst();
    

擦除getFirst的返回类型后返回Object类型,编译器自动插入String的强制类型转换。就是说,编译器把这个方法调用翻译为两条虚拟机指定:

(1)对原始方法TestGenericC.getFirst的调用;

(2)将返回的Object类型强制转换为String类型。

当存取一个泛型域时(如上例的first)一样要插入强制类型转换。

2.3、翻译泛型方法:(详见:《Java核心技术》卷1(原书第10版)第318页)

2.4、注意点:

(1)虚拟机中没有泛型,只有普通的类和方法;

(2)所有的类型参数都用它们的限定类型替换;

(3)桥方法被合成来保持多态;

(4)为保持类型安全性,必要时插入强制类型转换。

给大忙人看的Java核心技术笔记(6泛型编程)

要点:

  泛型类是带有一个或多个类型参数的类

  泛型方法是带有类型参数的方法

  可以要求类型参数必须是一个或者多个类型的子类型

  泛型类型是不变得:当S是T的子类型是,G<S>和G<T>没有关系

  通过使用通配符G<? extends T>或者 G<? super T>,你可以指定一个方法接受一个带子类或父类参数的泛型类型的实例

  当泛型类和方法被编译时,类型参数会被擦除

  类型擦除对泛型有诸多限制。特别是,不能实例化泛型类或数组。不能转换成泛型类型,或者抛出一个泛型类型对象。

  即使泛型类和方法在虚拟机中被擦除,你也可以在运行时找出他们是如何声明的。

1、泛型类

  ※类型参数不能用基本类型实例化。例如Entry<String, int>在Java中是无效的。

  当构造一个泛型类对象时,可以在构造函数中省略类型参数。

1 Entry<String, Integer> entry = new Entry<>("1",1);

2、泛型方法

  当声明一个反洗方法时,类型参数要放在修饰符之后,返回类型之前。当调用时,不要指定类型参数。它可以从方法的参数和返回类型中推断出来。

  也可以在调用时候显示的写出来

1 public static <T> void swap(T[] array, int i, int j);
2 Arrays.<String>swap(friends,0,1);

3、类型限定

  泛型类或方法的类型参数需要满足某些要求,或者是需要能够调用一些通用的方法。可以对类型做出限定。

  T extends AutoCloseable

  类型参数可以有多个限定:  T extends Runnable & AutoCloseable

  ※可以有多个接口限定,但最多只能有一个是类。如果有一个限定是类,则它必须放在限定列表的第一位。

 

以上是关于Java核心技术知识点笔记—泛型程序设计的主要内容,如果未能解决你的问题,请参考以下文章

给大忙人看的Java核心技术笔记(6泛型编程)

Java核心技术-泛型程序设计

特大好消息!阿里P8架构师花半年整理的java核心笔记,理论到实战全搞定

Java核心技术卷一 6. java泛型程序设计

读书笔记Java核心技术-基础知识-反射

Java核心技术 卷Ⅰ 基础知识