Java中的泛型(Generics)是JDK 5引入的一种特性,它使得类、接口和方法能够以一种类型参数化的方式进行定义和使用。泛型的主要目的是增强代码的类型安全性和可读性,同时减少类型转换(cast)操作。

泛型的基本概念

泛型允许我们在类、接口和方法中定义和使用参数化类型,即用一个占位符(类型参数)来表示实际类型。在实际使用时,具体类型会替换这些类型参数。

泛型类

定义一个带有类型参数的类:

public class Box<T> {
private T content; public void setContent(T content) {
this.content = content;
} public T getContent() {
return content;
}
}

使用泛型类时指定具体类型:

public class Main {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
String content = stringBox.getContent();
System.out.println(content); // 输出: Hello Box<Integer> intBox = new Box<>();
intBox.setContent(123);
int number = intBox.getContent();
System.out.println(number); // 输出: 123
}
}

泛型接口

定义一个带有类型参数的接口:

public interface Container<T> {
void add(T item);
T get(int index);
}

实现泛型接口时指定具体类型:

public class StringContainer implements Container<String> {
private List<String> items = new ArrayList<>(); @Override
public void add(String item) {
items.add(item);
} @Override
public String get(int index) {
return items.get(index);
}
}

泛型方法

定义一个带有类型参数的方法:

public class Util {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}

使用泛型方法:

public class Main {
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4};
String[] stringArray = {"Hello", "World"}; Util.printArray(intArray); // 输出: 1 2 3 4
Util.printArray(stringArray); // 输出: Hello World
}
}

泛型的高级特性

通配符

Java泛型中的通配符用于表示不确定的类型,可以用在类和方法的参数中。

  1. 无界通配符 (<?>)

    用于表示任意类型。
public static void printList(List<?> list) {
for (Object elem : list) {
System.out.println(elem);
}
}
  1. 有界通配符(上界) (<? extends T>)

    用于表示某个类型的子类型。
public static void printNumbers(List<? extends Number> list) {
for (Number number : list) {
System.out.println(number);
}
}
  1. 有界通配符(下界) (<? super T>)

    用于表示某个类型的父类型。
public static void addNumber(List<? super Integer> list) {
list.add(1); // 允许添加Integer或其子类类型的对象
}

泛型类型擦除

在Java中,泛型是在编译时处理的,编译后所有的泛型信息都会被擦除,这个过程被称为类型擦除(Type Erasure)。类型擦除会将泛型类型替换为其限定类型(通常是Object),并插入类型转换以保持类型安全。

例如,以下泛型类:

public class Box<T> {
private T content; public void setContent(T content) {
this.content = content;
} public T getContent() {
return content;
}
}

在编译后,大致会变成:

public class Box {
private Object content; public void setContent(Object content) {
this.content = content;
} public Object getContent() {
return content;
}
}

泛型的限制

由于类型擦除的存在,泛型在Java中有一些限制:

  1. 不能使用基本类型:泛型类型参数不能是基本类型(如intchar等),只能使用包装类型(如IntegerCharacter等)。
  2. 运行时类型查询:在运行时,无法获得泛型类型参数的信息,因此不能使用instanceofgetClass来检查泛型类型。
  3. 静态上下文中不能使用泛型类型参数:泛型类型参数不能用于静态变量、静态方法或静态代码块中。
  4. 不能创建泛型数组:例如new T[10]是不允许的,因为在运行时无法确定类型T

泛型的使用场景

泛型广泛应用于集合框架(如List<T>Map<K, V>等),使得代码更加类型安全,并提高了代码的重用性和可读性。

通过了解和使用Java中的泛型,可以编写更为灵活、安全和可维护的代码。

泛型(Generics)的更多相关文章

  1. [19/03/23-星期六] 容器_ 泛型Generics

    一.概念 生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据. 数组就是一种容器,可以在其中放置对象或基本类型数据. ---优势:是一种简单的线性序列,可以 ...

  2. 泛型(Generics)

    Framework类库中的泛型 泛型可以使代码重用,提高开发效率 CLR允许在引用类型.值类型或接口中定义泛型方法: CLR允许创建泛型引用类型.泛型值类型(枚举不允许创建).泛型委托类型和泛型接口类 ...

  3. Java 泛型(Generics)

    Generics, 类似C++中的模版. 允许在定义类和接口的时候使用类型参数(type parameters), 声明的类型参数在使用的时候用具体的类型来替换. 如 ArrayList<Str ...

  4. Java 泛型(Generics) 综述

    一. 引子 一般的类和方法.仅仅能使用详细类型:要么是基本类型.要么是自己定义类型.假设要编写能够应用于多种类型的代码,这样的刻板的限制对代码的束缚就会非常大. 多态算是一种泛化机制,但对代码的约束还 ...

  5. Welcome-to-Swift-22泛型(Generics)

    泛型代码可以确保你写出灵活的,可重用的函数和定义出任何你所确定好的需求的类型.你可以写出避免重复的代码,并且用一种清晰的,抽象的方式表达出来. 泛型是Swift许多强大特征中的其中一个,许多Swift ...

  6. [JavaCore]JAVA中的泛型

    JAVA中的泛型 [更新总结] 泛型就是定义在类里面的一个类型,这个类型在编写类的时候是不确定的,而在初始化对象时,必须确定该类型:这个类型可以在一个在里定义多个:在一旦使用某种类型,在类方法中,那么 ...

  7. Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

    Java1.5泛型指南中文版(Java1.5 Generic Tutorial) 英文版pdf下载链接:http://java.sun.com/j2se/1.5/pdf/generics-tutori ...

  8. java泛型小问题

    几年前当Java5还未正式发布的时候,看到过一些人写的介绍Tiger中的新特性,当时对我第一感觉冲击最大的就是泛型(generics)和注释(annotation),因为它们直接影响了我们编码的语法习 ...

  9. 泛型-----键值对----映射 hashmap--entry中key value 链表

    connection map 集合框架 * java.util.Collection *集合与数组相似,也是可以保存一组元素,并且提供了操作元素的相关方法. *collection是所有集合的顶级接口 ...

  10. Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)

    Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cgl ...

随机推荐

  1. 将 EasySQLite 从 .NET 8 升级到 .NET 9

    前言 EasySQLite是一个.NET 8操作SQLite入门到实战的详细教程,主要是对学校班级,学生信息进行管理维护.今天咱们的主要内容是将EasySQLite从.NET 8升级到.NET 9. ...

  2. JuiceFS 2024:开源与商业并进,迈向 AI 原生时代

    即将过去的 2024 年,是 JuiceFS 开源版本推出的第 4 年,企业版的第 8 个年头.回顾过去这一年,JuiceFS 社区版依旧保持着快速成长的势头,GitHub 星标突破 11.1K,各项 ...

  3. springboot-多模块构建-1

    1. 场景描述 先介绍下背景,项目为什么需要用多模块?springmvc难道还不够? (1)设计模式真言:"高内聚.低耦合",springmvc项目,一般会把项目分成多个包:con ...

  4. Golang-流程控制4

    http://c.biancheng.net/golang/flow_control/ Go语言if else(分支结构) 在Go语言中,关键字 if 是用于测试某个条件(布尔型或逻辑型)的语句,如果 ...

  5. 1.某道翻译js逆向sign值

    首先找到这个请求接口 这个接口就是我们请求翻译的接口 发现有个sign值,这就是我们需要逆向的值 再看看这个接口的响应 可以发现这个响应是被加密的,我们还需要去逆向解密这个被加密的响应,这篇就单纯讲一 ...

  6. redis如何设置密码

    密码设置 这里简单介绍一下redis如何设置密码redis密码设置有两种方式,一种需要重启redis服务,一种不需要重启redis服务. 首先,介绍一下需要重启redis服务的设置方式即找到redis ...

  7. 十二. Redis 集群操作配置(超详细配图,配截图详细说明)

    十二. Redis 集群操作配置(超详细配图,配截图详细说明) @ 目录 十二. Redis 集群操作配置(超详细配图,配截图详细说明) 1. 为什么需要集群-高可用性 2. 集群概述(及其搭建) 3 ...

  8. [记录点滴] luaxml编译过程

    [记录点滴] luaxml编译 记录一次luaxml编译的解决过程 参考 http://blog.csdn.net/dc_show/article/details/38957991 0x01 编译错误 ...

  9. Luogu P9055 [集训队互测 2021] 数列重排 题解 [ 紫 ] [ 构造 ] [ 数学 ]

    数列重排:差点就场切的神仙构造,最后一步想假了,导致我模拟赛荣获 25+5+0 的好成绩! 这题部分分很有启发性,跟着一步一步打基本能想到正解的构造,但也有可能想偏部分分的意思,想假策略. 构造 先看 ...

  10. Halcon学习教程(一) 之提取十字线中心 图像分割

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/17266405.html 废话不多说,因为毕业后工作原因比较忙,好久没更新博客了,直接上图... ...