Java 之路 (十五) -- 泛型上(泛型类、泛型方法、有界类型参数、泛型与继承、类型推断)

Thinking in Java 中关于泛型的讲解篇幅实在过长,前后尝试阅读这一章,但总是觉得找不到要点,很迷。于是放弃 Thinking in Java 泛型一章的阅读,转而官方教程,本章可以算作官方教程的中文版。

放上官方教程地址:

The Java™ Tutorials - Generics


1.为什么使用泛型

简单来说,泛型使类型在定义类、接口和方法时成为参数。就像在方法声明中使用形式参数一样,类型参数提供了一种使用不同输入重用相同代码的方法。不同之处在于形式参数的输入是值,而类型参数的输入是类型。

使用泛型的代码比非泛型代码有许多好处:

  • 在编译时进行更强大的类型检查。
    Java编译器将强类型检查应用于通用代码,并在代码违反类型安全时发出错误。修复编译时错误比修复运行时错误更容易,后者很难发现错误源头。

  • 消除转型

    以下没有泛型的代码片段需要强制转换:

    List list = new ArrayList();
    list.add("hello");
    String s = (String)list.get(0);

    使用泛型时,不需要类型转换:

    List <String> list = new ArrayList<String>();
    list.add("hello");
    String s = list.get(0); //没有转型
  • 使程序员能够实现通用算法。
    通过使用泛型,程序员可以实现通用算法,这些算法可以处理不同类型的集合,可以自定义,并且类型安全且易于阅读。


2. 泛型类

泛型类是对类型进行参数化的类或接口。 下面一步步展示该概念。

2.1 简单的 Box 类

如果我们想在一个类中存放任何类型的对象,怎么做呢?没错,使用 Object 即可。

下面展示一个可对任何类对象进行操作的非泛型 Box 类:

public class Box {
   
    private Object object;

    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

由于它的方法接受或返回一个Object ,所以你可以自由地传入任何你想要的东西。 在编译时无法验证类的使用方式。 代码的一部分可能会放置一个Integer ,并期望从中获取Integer ,而代码的另一部分可能会错误地传入String ,从而导致运行时错误。

2.2 Box 类的泛型版本

上面提到,通过 Object 存储,不存在任何类型信息,这可能导致使用时类型错误。于是泛型发挥作用了。

泛型类定义格式如下:

class name<T1, T2, ..., Tn> { /* ... */ }

用尖括号将类型参数包起来,并跟在类名后面。

于是2.1中的代码修改之后如下:

public class Box<T> {
   
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

如代码所示,所有 Object 都被 T 替换。类型变量可以是制定的任何非基本类型:类、接口、数组或者其他类型变量。且类型变量 T 可以在类的任何位置使用。

同样,也适用于将泛型应用于接口,如下:

interface Box<T> { /*...*/}

2.3 类型参数命名约定

按照惯例,类型参数名称是单个大写字母 。

最常用的类型参数(标识符)名称是:

  • E - Element(Java Collections Framework广泛使用)
  • K - key
  • N - number
  • T - 类(类型)
  • V - value
  • S,U,V等 - 第2,第3,第4类型

2.4 调用和实例化泛型类

将 T 替换为某些具体类即可,例如 Integer:

 Box<Integer> integerBox = new Box<Integer>();

//在 Java SE 7 及更高版本中,只要编译期可以从上下文中确定或推断类型参数,就可以用一组空的类型参数“<>” 替换调用泛型类的构造函数所需的类型参数
//如下:
 Box<Integer> integerBox = new Box<>();

泛型类的调用通常称为参数化类型

2.5 多种类型参数

泛型类可以有多个类型参数,如下展示一个通用的 OrderPair 类,实现了 Pair 接口:

public interface Pair<K, V> {
   
    public K getKey();
    public V getValue();
}

public class 
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值