java泛型程序设计——类型变量限定 + 泛型代码和虚拟机

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 类型变量限定 + 泛型代码和虚拟机 的知识;


【1】类型变量的限定

1.1)类和方法需要对类型变量加以限定

  • 1.1.1)看个荔枝:
class ArrayAlg
{
    public static <T> T min(T[] a)
    {
        if(a == null || a.length==0) return null;
        T smallest = a[0];
        for(int i=1;i<a.length;i++)
        if(smallest.compareTo(a[i]) > 0) smallest = a[i];
        return smallest;
    }
}

对以上代码的分析(Analysis):

  • A1)出现的问题:变量smallest 的类型为 T ,意味着它可以是任何一个类的对象。怎么才能确定T 所属的类有 compareTo 方法呢?
  • A2)解决方法:将T 限制为 实现了 Comparable 接口(只含有一个compareTo的标准接口)的类。 可以通过对类型变量T设置限定实现这一点:
public staitc <T extends Comparable> T min(T[] a);
  • 现在, 泛型的main方法只能被实现了 Comparable 接口的类(如 String, Date 等)的数组调用。 由于 Rectangle 类没有实现 Comparable接口, 所以调用min 方法将会产生一个编译错误;

A3)读者奇怪: 为什么使用关键字extends 而不是 implemens , 因为Comparable是一个接口。
A3.1)看个荔枝: 表示T 应该是绑定类型的子类型。T 和 绑定类型可以是类, 也可以是接口。 选择关
键字extends 的原因是更接近子类的概念, 并且 java 的设计者也不打算在语言中再添加一个新的 关键字;
1.2)一个类型变量或通配符可以有多个限定, 如

T extends Comparable & Serializable 限定类型用 & 分割, 而逗号用来分割类型变量;

1.3)在java继承中, 可以根据需要拥有多个接口超类型, 但限定中至多有一个类。 如果用一个类作为限定, 它必 须是限定列表中的第一个;
1.4)看个荔枝:


【2】泛型代码和虚拟机

2.1)虚拟机没有泛型类对象——所有对象都属于普通类;

  • 2.1.1)原始类型:无论何时定义一个泛型类型, 都自动提供了一个相应的 原始类型。 原始类型的名字就是删去类型参数后的泛型类型名。
  • 2.1.2)擦除操作: 擦除类型变量, 并替换为 限定类型(无限定的变量用 Object, 如只有T,没有 T extends Comparable 的限定类型);
  • 2.1.3)看个荔枝: Pair(下图中的代码) 的原始类型(下面的源代码)如下,
    这里写图片描述
public class Pair
{
   private Object first;
   private Object second;

   public Pair() { first = null; second = null; }
   public Pair(Object first, Object second) { this.first = first;  this.second = second; }

   public Object getFirst() { return first; }
   public Object getSecond() { return second; }
   public void setFirst(Object newValue) { first = newValue; }
   public void setSecond(Object newValue) { second = newValue; }
}

对以上代码的分析(Analysis):

  • A1)因为T是一个无限定的变量,所以直接用 Object 替换;
  • A2)在程序中可以包含不同类型的 Pair ,如 Pair, Pair , 而擦除类型后就变成原始的Pair 类型了;

2.2)原始类型用第一个限定的类型变量来替换, 如果没有给定限定就用 Object替换。

  • 2.2.1)没有限定类型: 如上述荔枝中的 Pair 没有类型变量没有限定(没有 T extends … 语句), 因此,原始类型用 Object 替换T;
  • 2.2.2)但是如果T有限定的话: 如 T extends Comparable & Serializable , 看个荔枝:
 public class Interval<T extends Comparable & Serializable> implements Serializable
{
    private T lower;
    private T upper;

    public Interval(T first, T second){}
}
  • 原始类型 Interval 如下所示:
public class Interval implements Serializable
{
    private Comparable  lower;
    private Comparable  upper;

    public Interval(Comparable  first, Comparable  second){}
}

Annotation)

  • A1)如果切换限定:class Interval 《Serializable & Comparalbe> 会发生什么?
  • A2)如果这样做 : 原始类型用 Serializable 替换T , 而编译器在必要时要向 Comparable 插入强制类型转换。
  • A3)为了提高效率: 应该将标签(tagging) 接口(即没有方法的接口)放在边界列表的末尾;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛型Java 中的一种特殊语法,它允许在编译时期对程序中使用的数据类型进行参数化。使用泛型可以增强程序的类型安全性,使代码更加简洁和通用。以下是一些 Java 泛型程序的示例: 1. 泛型类 以下是一个泛型类的示例,它可以存储任何类型的数据: ``` public class Box<T> { private T data; public Box(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } } ``` 在这个示例中,`Box` 类有一个类型参数 `T`,它可以代表任何数据类型。在实例化 `Box` 类时,我们可以指定具体的类型参数,例如: ``` Box<String> stringBox = new Box<>("Hello, world!"); Box<Integer> intBox = new Box<>(42); ``` 2. 泛型方法 以下是一个泛型方法的示例,它可以比较两个对象的大小: ``` public static <T extends Comparable<T>> int compare(T a, T b) { return a.compareTo(b); } ``` 在这个示例中,`compare` 方法有一个类型参数 `T`,它必须是 `Comparable` 接口的子类型。这个方法可以比较任何实现了 `Comparable` 接口的对象,例如: ``` Integer a = 1, b = 2; int result = compare(a, b); // 返回 -1 ``` 3. 通配符 以下是一个使用通配符的示例,它可以打印任何类型的列表: ``` public static void printList(List<?> list) { for (Object o : list) { System.out.println(o); } } ``` 在这个示例中,`printList` 方法接受一个 `List` 类型的参数,这个参数是一个通配符类型,表示可以接受任何类型的列表。在方法内部,我们使用 `Object` 类型变量来遍历这个列表,并打印每个元素的值。例如: ``` List<String> stringList = Arrays.asList("Hello", "world"); List<Integer> intList = Arrays.asList(1, 2, 3); printList(stringList); // 输出 "Hello" 和 "world" printList(intList); // 输出 1、2 和 3 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值