Java编程思想__泛型(一)

本文探讨了Java泛型的概念,对比了Java泛型与C++模板的异同,并通过实例介绍了泛型在简单容器、元组类库、堆栈、随机列表、泛型接口、泛型方法等方面的应用。文章强调了泛型提高代码可复用性和类型安全性的优点,同时也揭示了其在某些场景下的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 一般的类和方法,只能使用具体的类型,要么是基本类型,要么是自定义的类。如果要编写可以适用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
  • 在面向对象编程语言中,多态是一种泛化机制。
  • JavaSE5 的重大变化之一: 泛型的概念。泛型实现了参数化类型的概念,使代码可以应用于多种类型。泛型 这个术语的意思是 : 适用于许多许多的类型
  • 如果你了解其他语言(例如C++) 中的参数化类型机制,你就会发现,有些以前能够做到的事情,使用Java泛型机制缺无法做到。使用别人构建好的泛型类型相当容易。但是如果你要自己创建一个泛型实例,就会遇到很多令人吃惊的事情。
  • 这并非说Java泛型毫无用处。在很多情况下,它可以使代码更直接更优雅。不过,瑞国你具备其他语言的经验,而那种语言实现了更纯粹的泛型,那么,Java可能令你失望了。

 

Java泛型与C++的比较

  • Java的设计者曾说过,设计这门语言的灵感主要来自C++。

  1.  了解C++模板的某些方面,有助于你理解泛型的基础。同时,非常重要的一点是,你可以了解Java泛型的局限是什么,以及为什么会有这些限制。最终目的是帮助你理解,Java泛型的边界在哪里。因为你只有知道某个技术不能做到什么,你这样才能更好地做到所能做的。

  2. Java社区中,人们普遍对C++模板有了一种误解,而这种误解可能会误导你,令你在理解泛型的意图时产生偏差。

 

简单泛型

  • 有很多原因促成了泛型的出现,最引人注目的一个原因是,就是为了创造容器类。容器,就是存放要使用的对象的地方。数组也是如此,不过与简单的数组相比,容器更加灵活,具备更多不同的功能。
//一个只能持有单个对象的类,这个类可以明确指定其持有的对象的类型 ,如下例子


public class Automobile {}

class Holder1{
    private Automobile automobile;

    public Holder1(Automobile automobile) {
        this.automobile = automobile;
    }
    Automobile getAutomobile(){
        return automobile;
    }
}
  1. 这个类有以下问题 : ①可重用性不好 ②无法持有其他类型的任何对象 
//JavaSE 5 之前,我们可以在类中直接持有Object类型的对象

public class Holder2 {
    private Object object;

    public Holder2(Object object) {
        this.object = object;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
    public static void main(String[] args) {
        Holder2 holder2 = new Holder2(new Automobile());
        //把object 强制转型为 Automobile
        Automobile automobile = (Automobile) holder2.getObject();

        //设置对象的属性
        holder2.setObject("the object is Automobile");
        //获取对象的属性
        String string = (String) holder2.getObject();

        holder2.setObject(1);
        Integer a= (Integer) holder2.getObject();
    }
}
  1. Holder2 可以存储任何类型的对象,在这个例子中,只用了一个Holder2对象,却先后存储了三种不同类型的对象 (Automobile , String ,Integer 三个对象)。
  2. 有些时候,我们确实希望容器能够同时持有多种类型的对象。但是,通常而言,我们只会使用容器来存储一种类型的对象。泛型的主要目的之一就是指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性
public class Holder3 <T>{
    private T t;

    public Holder3(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public static void main(String[] args) {
        Holder3<Automobile> holder3 = new Holder3<Automobile>(new Automobile());
        Automobile automobile = holder3.getT();
        //如下会报错
        //holder3.setT(1);  setT(参数必须为 Automobile 类型)
    }
}
  1. 当你创建Holder3 对象时,必须指明有什么类型的对象,将其置于尖括号内。就像 main() 中那样。然后,你就只能在 Holder3 中存入该类型(或其子类,因为多态与泛型不冲突)的对象了。
  2. 在你从 Holder3 中取出它持有的对象时,自动地就是正确的类型。
  3. 这就是Java 泛型的核心概念: 告诉编译器想使用什么类型,然后编译器帮你处理一切细节

 

一个元组类库

  • 仅一次方法调用就能返回多个对象,你应该经常需要这样的功能吧。可是 return 语句只允许返回单个对象,因此,解决办法就是创建一个对象,用它来持有想要返回的多个对象。
  • 当然,可以在每次需要的时候,专门创建一个类来完成这样的工作。可是有了泛型,我们就能够一次性地解决该问题,以后再也不用在这个问题上浪费时间了。同时,我们再编译期就能确保类型安全。这个概念被称为 元组
  • 元组:  它是将一组对象直接打包存储于其中的一个单一对象。这个容器对象允许读取其中元素,但是不允许向其中存放新的对象。(这个概念也被称为 数据传送对象或信使)
//如下 是一个2维元组,它能够持有两个东西

public class TwoTuple<A,B> {
    public final A a;
    public final B b;

    public TwoTuple(A a, B b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public String toString() {
        return "TwoTuple{" +
                "a=" + a +
                ", b=" + b +
                '}';
    }
}
  1. 构造器捕获了要存储对象,而toString() 是一个便利函数,用来显示列表中的值。注意,元组隐含地保持了其中元素的次序。
  2. 问题发现:  第一次阅读上面的代码时,你也许会想,这不是违反了 Java编程的安全性原则吗? 
  3. a 和 b 应该声明为 private ,然后提供 getA() 和 getB() 之类的访问方法才对呀? 让我们仔细看看这个例子中的安全性: 客户端程序可以读取 a 和 b 对象,然后可以随心所欲地使用 这两个东西。但是 ,它们却无法将其他赋值 赋予 a和 b 。因为 final 声明 为你买了相同的安全保险,而且这种格式更简洁明了。
  4. 还有另一种设计考虑,即你确实希望允许客户端程序员改变 a 和 b 所引用的对象。然而, 采用以上的形式无疑是更安全的做法,这样的话,如果程序员想要使用具体具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值