【Java】泛型 之 编写泛型

2023-09-22 15:18:42

写泛型类比普通类要复杂。通常来说,泛型类一般用在集合类中,例如ArrayList<T>,我们很少需要编写泛型类。

如果我们确实需要编写一个泛型类,那么,应该如何编写它?

可以按照以下步骤来编写一个泛型类。

首先,按照某种类型,例如:String,来编写类:

public class Pair {
    private String first;
    private String last;
    public Pair(String first, String last) {
        this.first = first;
        this.last = last;
    }
    public String getFirst() {
        return first;
    }
    public String getLast() {
        return last;
    }
}

然后,标记所有的特定类型,这里是String

public class Pair {
    private String first;
    private String last;
    public Pair(String first, String last) {
        this.first = first;
        this.last = last;
    }
    public String getFirst() {
        return first;
    }
    public String getLast() {
        return last;
    }
}

最后,把特定类型String替换为T,并申明<T>

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() {
        return first;
    }
    public T getLast() {
        return last;
    }
}

熟练后即可直接从T开始编写。

静态方法

编写泛型类时,要特别注意,泛型类型<T>不能用于静态方法。例如:

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public T getLast() { ... }

    // 对静态方法使用<T>:
    public static Pair<T> create(T first, T last) {
        return new Pair<T>(first, last);
    }
}

上述代码会导致编译错误,我们无法在静态方法create()的方法参数和返回类型上使用泛型类型T。

有些同学在网上搜索发现,可以在static修饰符后面加一个<T>,编译就能通过:

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public T getLast() { ... }

    // 可以编译通过:
    public static <T> Pair<T> create(T first, T last) {
        return new Pair<T>(first, last);
    }
}

但实际上,这个<T>Pair<T>类型的<T>已经没有任何关系了。

对于静态方法,我们可以单独改写为“泛型”方法,只需要使用另一个类型即可。对于上面的create()静态方法,我们应该把它改为另一种泛型类型,例如,<K>

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public T getLast() { ... }

    // 静态泛型方法应该使用其他类型区分:
    public static <K> Pair<K> create(K first, K last) {
        return new Pair<K>(first, last);
    }
}

这样才能清楚地将静态方法的泛型类型和实例类型的泛型类型区分开。

多个泛型类型

泛型还可以定义多种类型。例如,我们希望Pair不总是存储两个类型一样的对象,就可以使用类型<T, K>:

public class Pair<T, K> {
    private T first;
    private K last;
    public Pair(T first, K last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public K getLast() { ... }
}

使用的时候,需要指出两种类型:

Pair<String, Integer> p = new Pair<>("test", 123);

Java标准库的Map<K, V>就是使用两种泛型类型的例子。它对Key使用一种类型,对Value使用另一种类型。

小结

编写泛型时,需要定义泛型类型<T>

静态方法不能引用泛型类型<T>,必须定义其他类型(例如<K>)来实现静态泛型方法;

泛型可以同时定义多种类型,例如Map<K, V>

更多推荐

Flink1.14 Source概念入门讲解与源码解析

目录FlinkSource概念SourceSource源码getBoundedness()createReader(SourceReaderContextreaderContext)createEnumerator(SplitEnumeratorContextenumContext)SplitEnumeratorres

Redis的高性能之谜

介绍Redis通常用作缓存。当一致性要求不高时,它也可以用作存储。此外,Redis还提供消息订阅、事务、索引等功能。我们还可以使用集群功能构建分布式存储服务,并实现非强一致性的分布式锁服务。在上述各种情况下,Redis都具有一个共同的优势,即处理速度快(高性能)。Redis有多快?要了解Redis有多快,您需要有一个评

MySQL数据库入门到精通3--进阶篇(存储引擎,索引)

1.存储引擎1.1MySQL体系结构1).连接层最上层是一些客户端和链接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接

怎样使用 NFTScan Solana API 快速创建 NFT 应用程序?

之前,Solana凭借其超高的性能和低廉的费用,已然成为NFT项目最青睐的公链之一,众多知名NFT项目如DeGods、OkayBears、DegenerateApeAcademy等都选择在Solana上发行。意味着Solana链上每天都会产生海量的NFT交易数据,仅交易记录就超过了数百万条。不仅如此,Solana新建钱

java 企业工程管理系统软件源码 自主研发 工程行业适用

工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理工程项目各模块及其功能点清单一、系统管理1、数据字典:实现对数据字典标签的增删改查操作2、编码管理:实现对系统编码的增删改查操作3、用户管理:管理和查看用户角

【C++】STL之适配器---用deque实现栈和队列

目录前言一、deque1、deque的原理介绍2、deque的底层结构3、deque的迭代器4、deque的优缺点4.1、优点4.2、缺点二、stack的介绍和使用1、stack的介绍2、stack的使用3、stack的模拟实现三、queue的介绍和使用1、queue的介绍2、queue的使用3、queue的模拟实现前

Python:为何成为当下最热门的编程语言?

文章目录🍋引言🍋1.简单易学🍋2.多领域应用🍋3.强大的社区支持🍋4.丰富的库和框架🍋5.跨平台兼容🍋6.开源和免费🍋7.数据科学和人工智能的崛起🍋8.自动化和脚本编写🍋9.大型组织的采用🍋10.教育和培训🍋引言在计算机编程的世界里,有数以百计的编程语言可供选择。然而,近年来,Python已经崭

偶现来电时手机操作出现重启

问题描述:偶现来电时手机操作出现重启问题分析:从系统Log看09-0610:22:44.79182914001425WWatchdog:***WATCHDOGKILLINGSYSTEMPROCESS:Blockedinhandleronmainthread(main)09-0610:22:44.794133140014

CSRF和SSRF有什么不同?

文章目录CSRF复现SSRF复现启动环境漏洞复现探测存活IP和端口服务计划任务反弹shell区别CSRF复现打开dvwa,将难度调为low,点击CSRF,打开后发现有一个修改密码的输入框:在这里修改密码,并用bp抓包,在httphistory查看数据包,点击engagementtools中的GenerateCSRFPo

策略模式,一种广泛应用于各种情况的设计模式(设计模式与开发实践 P5)

文章目录策略模式实现思想实战-表单策略模式定义:定义一系列算法,把它们一个个封装起来,并且可以互相替换例如,我们要计算年终奖,年终奖根据绩效A、B、C来计算最终数值实现最初我们很容易想到用分支if来解决这个问题,如果绩效=A则工资x2,如果绩效=B则工资x3如果经常使用这样的分支结构,你会发现代码耦合度很高,很容易就出

瑞芯微RK3568:Debian系统如何安装Docker

本文基于HD-RK3568-IOT评估板演示Debian系统安装Docker,该方法适用于RK356X全系产品。HD-RK3568-IOT评估板基于HD-RK3568-CORE工业级核心板设计(双网口、双CAN、5路串口),接口丰富,适用于工业现场应用需求,亦方便用户评估核心板及CPU的性能。适用于工业自动化控制、人机

热文推荐