Java——泛型

【泛型】Java中的泛型,泛型类,泛型接口,泛型方法,泛型擦除 这篇文章总结一下Java中的泛型相关知识点,包括:泛型概念、泛型优缺点、泛型通配符、泛型上下界、泛型使用(泛型类、泛型接口、泛型方法)、泛型擦除等内容。 一、泛型概念 (1)什么是泛型 什么是泛型??? 泛型(Generic),是一种参数化数据类型,它允许我们在编写程序代码的时候不用具体指定需要什么数据类型,而是等到具体使用的时候,将数据类型以参数的形式传递给程序,这就是泛型程序设计。 (2)为什么需要泛型 我们来看看下面这个栗子 假设现在有个需求,通过集合保存元素,需要保存String字 阅读详情

引出泛型

先来看下面一串代码

class MyArrayList {

    public int usedSize;
    public int[] arr;

    public MyArrayList() {
        this.arr = new int[10];
    }

    public void add(int val) {
        arr[usedSize] = val;
        usedSize++;
    }
}

public class Test {

    public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
    }
}

可以看到顺序表可以添加整形元素,那么如果要添加String类型的呢

可以看到会报错,那如果想要放字符串类型的元素是不是要再重新写一个MyArrayList类,那是不是也太麻烦了

这里就要引出java中提供的泛型语法

什么是泛型

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。简单来说就是,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。

语法:

class 泛型类名称<类型形参列表>

泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
 

所以上述代码可以改为

class MyArrayList<T> {

    public int usedSize;
    public T[] arr;

    public MyArrayList() {
        this.arr = (T[])new Object[10];
    }

    public void add(T val) {
        arr[usedSize] = val;
        usedSize++;
    }
}

public class Test {

    public static void main(String[] args) {
        //存放String类型
        MyArrayList<String> myArrayList1 = new MyArrayList<>();
        myArrayList1.add("abc");
        myArrayList1.add("xyz");
        
        //存放int类型
        MyArrayList<Integer> myArrayList2 = new MyArrayList<>();
        myArrayList2.add(1);
        myArrayList2.add(2);
    }
}

这样就实现了通用

这里还有一个疑问?

这个数组为什么实例化的时候要new 一个object类,还要强制类型转换呢?

这里就要说到泛型的擦除机制了 

什么时擦除机制

泛型逻辑语法比较难,具体的泛型擦除机制可以看这篇文章:https://zhuanlan.zhihu.com/p/51452375

在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。

所以在编译期间T就会被擦除为object,明明时new的object[] ,T也会被擦除为object,那为啥还要强制类型转换?

  • 编译器的视角:

    • T 是一个“未知但具体的类型”(比如 String、Integer 等)。

    • new Object[10] 创建的是 Object[],而 T[] 理论上应该是 String[]、Integer[] 等。

    • 直接赋值 T[] arr = new Object[10] 会导致类型不匹配(因为 Object[] 不是 T[] 的子类型),所以需要强制转换。

  • 运行时的实际行为:

    • 由于类型擦除,T[] 在运行时就是 Object[],所以强制转换 (T[]) 实际上什么都不做。

    • 但编译器会插入 隐式的类型检查,确保后续对 arr 的操作符合 T 的约束(比如不能存入非 T 类型的值)。

 为什么不能直接new T[] ?

  • 数组在运行时需要知道具体的类型(比如 String[] 和 Integer[] 是不同的)。

  • 但泛型 T 在运行时被擦除为 Object,无法确定应该创建 String[] 还是 Integer[]。

  • 如果允许 new T[],可能会导致错误的数组存储(比如把 Integer 存入 String[])。

所以 Java 强制要求开发者使用 Object[] + 强制转换的方式,并自行保证类型安全。

 上述泛型的中被擦除后一定时object吗?

不一定的,擦除后变成的类型时T的上界,那什么是泛型的上界?

语法定义:

class 泛型类名称<类型形参 extends 类型上边界> 

代码示例:

实例化的时候只能传入类型上边界或者其子类

class Person {
    
}
class Student extends Person {
    
}
class AAA {
    
}
class MyArrayList<T extends Person> {
    
}

public class Test {

    public static void main(String[] args) {
        MyArrayList<Student> myArrayList1 = new MyArrayList<>();
        MyArrayList<Person> myArrayList2 = new MyArrayList<>();
                
      
    }
}

如果传入AAA呢,AAA没由继承Person,可见会报错

 接下来我们讲通配符

class Message<T> {
    private T message ;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }

}
public class TestDemo {
    
    public static void fun(/*这里的类型接收*/Message<String> temp) {
        System.out.println(temp.getMessage());
    }

    public static void main(String[] args) {
        Message<String> message = new Message<>();
        message.setMessage("i love china");
        fun(message);
    }
}

看到类型接收的地方,如果换成传入的int类型,这里就会报错

此时也要把 接受类型改为Integer

同样也不具有一般性,这里就要用到通配符了,通配符就是把类型换成 ?(问号)

通配符更改后

public class TestDemo {

    public static void fun(/*这里的类型接收*/Message<?> temp) {
        System.out.println(temp.getMessage());
    }

    public static void main(String[] args) {
        Message<String> message1 = new Message<>();
        Message<Integer> message2 = new Message<>();

        message1.setMessage("i love china");
        message2.setMessage(99);
        fun(message1);
        fun(message2);
    }
}

这样就具有通用性了

通配符不仅由上界,同时还具有下界

? extends 类:设置通配符上限
? super 类:设置通配符下限
 

class Food {

}
class Fruit extends Food {

}
class Apple extends Fruit {

}
class Banana extends Fruit {

}
class Message2<T> { // 设置泛型
    private T message ;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }

}

public class TestDemo2 {
    // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
    public static void fun(/*传入类型*/Message2<? extends Fruit> temp){
        //temp.setMessage(new Banana()); //仍然无法修改!
        //temp.setMessage(new Apple()); //仍然无法修改!
        System.out.println(temp.getMessage());
    }

    public static void main(String[] args) {
        Message2<Apple> message = new Message2<>() ;
        message.setMessage(new Apple());
        fun(message);

        Message2<Banana> message2 = new Message2<>() ;
        message2.setMessage(new Banana());
        fun(message2);

    }

}

此时那个传入类型必须是fruit或者其子类,同时接受的值也不能修改

通配符的下界

class Food {

}
class Fruit extends Food {

}
class Apple extends Fruit {

}
class Plate<T> {
    private T plate ;

    public T getPlate() {
        return plate;
  }

  public void setPlate(T plate) {
        this.plate = plate;
 }
}
public class TestDemo3 {
    public static void fun(Plate<? super Fruit> temp){
        // 此时可以修改!!添加的是Fruit 或者Fruit的子类
        temp.setPlate(new Apple());//这个是Fruit的子类
        temp.setPlate(new Fruit());//这个是Fruit的本身
        //Fruit fruit = temp.getPlate(); 不能接收,这里无法确定是哪个父类
        System.out.println(temp.getPlate());//只能直接输出
    }

    public static void main(String[] args) {
        Plate<Fruit> plate1 = new Plate<>();
        plate1.setPlate(new Fruit());
        //通配符的下界,不能进行读取数据,只能写入数据。

        fun(plate1);

        Plate<Food> plate2 = new Plate<>();
        plate2.setPlate(new Food());
        fun(plate2);
    }

}

使用 <? super T> 表示,它表示 “某个未知类型,但必须是 T 或其父类”,上述函数的接受值必须是fruit本身或者他的父类

 

Windows 10下Carla 0.9.15安装避坑指南:从下载到运行的全流程解析 本文详细解析了在Windows 10系统上安装和运行Carla 0.9.15自动驾驶仿真平台的全流程。内容涵盖从系统环境准备、资源下载、Python依赖安装,到首次启动验证及常见错误(如DLL缺失、显卡驱动问题)的深度解决方案,旨在帮助用户快速搭建稳定的开发环境,并运行第一个自动驾驶Python脚本。 阅读详情

相关推荐

abaqus 6.13安装(ubuntu 16.04LTS)

1。从iso将文件拷贝出来 2。chmod 777 -R ./* 给文件权限 3。sudo /home/xx/A/setup 4。安装licenseserver 5。拷贝lic,log文件 6。打开license sudo ./lmgrd -c path 7. 27011@xx or 27011@localhost ...

a1099313374的博客 1950

Java之泛型

一、什么是泛型 1.背景: JAVA推出泛型以前,程序员可以构建一个元素类型为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。 2.概念: Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。 3.好处: 类型安全 消

Beyondczn的博客 9373

rsyslog交叉编译(armv7、armv8、aarch64、arm32平台通用)

该文档描述了如何交叉编译rsyslog到arm64嵌入式平台。

sinat_33909696的博客 1560

Java泛型详解:Java泛型集合、泛型类、泛型方法、泛型的使用

在 Java 1.5 之前没有泛型,通常需要使用强制类型转换的方式将一种数据类型转换为另一种数据类型,这种转换要求开发者对实际参数的类型具有可预知性。对于强制类型转换错误的情况,编译器可能不会提示错误,但是在运行时会出现异常,这是一个安全隐患。 为了解决这一隐患,从 Java 1.5 开始提供了泛型。泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。本节将详...

jijiangpeng的博客 7432

生物信息学新手必看:MAFFT多序列比对从安装到实战(附参数优化技巧)

本文为生物信息学新手提供了MAFFT多序列比对工具的完整指南。从Linux环境下的安装部署,到核心算法策略(如FFT-NS-i、L-INS-i)的选择逻辑,再到空位罚分等关键参数的深度解析与优化技巧,手把手教你完成从原始序列到高质量比对结果的实战流程,为后续进化树构建等分析奠定坚实基础。

weixin_29230773的博客 483

BERT + BiLSTM-CRF 处理流程

BERT是一个基于 Transformer 的预训练语言模型。与传统的语言模型不同,BERT 是双向的,即它同时利用上下文信息进行词表示学习。BERT 在大规模语料库上进行预训练,可以捕捉到深层次的语言知识和上下文关系,生成非常丰富的词向量表示。在序列标注任务中,BERT 被用作输入文本的编码器,将每个词映射为上下文相关的词嵌入(embeddings)。

AI Agent 首席体验官 2255

Java泛型——为何要有泛型

对于String类类型来说,它是继承自Object的,而Integer的直接父类是Number,因此会有Integer无法转String的错误。泛型类是在实例化类的时候指明泛型的具体类型,那么泛型方法就是在调用方法时指明泛型的具体类型。在实现传入泛型实参的泛型接口的实现类定义中,实现类即使不声明泛型,也不会编译错误。在实现未传入泛型实参的泛型接口的实现类定义中,实现类要声明泛型,否则会编译错误。为了避免这样可能的错误,引入泛型,使编译器在编译阶段就提示不匹配的类类型。方法返回了一个更加特定的返回类型。

xiaovie的博客 1719

流式数据湖存储技术,Apache Paimon是什么?

是一项流式数据湖存储技术,可以为用户提供高吞吐、低延迟的数据摄入、流式订阅以及实时查询能力。Paimon 采用开放的数据格式和技术理念,可以与 Apache Flink / Spark / Trino 等诸多业界主流计算引擎进行对接,共同推进 Streaming Lakehouse 架构的普及和发展。

一个写湿的程序猿 2万+

java泛型——泛型类、泛型方法、泛型接口

泛型Java 泛型Java 泛型是什么泛型类泛型类的格式泛型类举例泛型方法泛型方法的格式泛型方法举例泛型接口泛型接口的格式泛型接口举例 Java 泛型 Java 泛型是什么 官方定义: 泛型是Java SE 1.5的新特性,泛型的本质就是参数化类型,也就是说所操作的数据类型被指定为一个参数 这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类、泛型接口、泛型方法 优缺点: ​ 优点:可以不用再类型转换了 ​ 缺点:降低了代码的可读性 泛型类 泛型类:当一个类要操作的引用数据类型不确定的时候,可

一个小小的码农 6583

56-FMC连接器电路设计

FMC连接器电路设计

weixin_66510961的博客 4721

归结法证明真题分析

本文主要探讨了逻辑证明题的三种核心形式及其解题策略。第一类为A1∧A2∧A3→B的证明,常采用线性、单元、支持策略法等归结法,典型案例包括使用归纳法证明特定逻辑公式,并列举了历年真题。第二类为集合交集证明,典型案例为证明任意集合S和T的交集S∩T是S的子集,需将交集和包含关系用逻辑式表达。第三类为常规归结法证明,真题示例为使用归结法证明特定逻辑蕴含关系。掌握前两类证明方法后,第三类问题自然迎刃而解。

super_mochi1 278

Java泛型

是同时存在的,可是如果是常规的两个方法,他们的方法签名是一样的,也就是说虚拟机根本不能分别这两个方法。如果是我们自己编写Java代码,这样的代码是无法通过编译器的检查的,但是虚拟机却是允许这样做的,因为虚拟机通过参数类型和返回类型来确定一个方法,所以编译器为了实现泛型的多态允许自己做这个看起来“不合法”的事情,然后交给虚拟器去区别。如果是重载,那么子类中两个setValue方法,一个是参数Object类型,一个是Date类型,可是我们发现,根本就没有这样的一个子类继承自父类的Object类型参数的方法。

YLXCA的博客 1315

基于C++和Qt开发IEC104规约主站调试软件(第二章)

本章节主要讲解iec104主站软件界面设计和从站的连接功能以及部分功能代码的展示。

半青年的博客 858

【 java 泛型】详解java泛型

java泛型可以提高java程序的类型安全,提高程序的可靠性,并且在开发中也较常用,因此还是要简单学习一下!

阿牛的博客 2069

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Java 泛型

Java 泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。泛型信息不会进入到运行时阶段。编译器有效 泛型的三种方式:泛型类、泛型接口、泛型方法 泛型类 定义格式: 修饰符 class 类名<代表泛型的变量> { } 例如,API中的ArrayList集合: class ArrayList<E>{ p

JustToFaith 2955

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java之泛型,什么是泛型?为什么用泛型?(泛型详解)

1.为什么会有泛型呢? 早期的Object类型可以接受任意的对象类型,但是在实际使用中,会有类型转化的问题,存在隐患,所以Java提供泛型解决这个安全问题 2.什么是泛型? 泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类...

围巢 3969

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java泛型

文章目录1. 泛型简述2. 泛型类别2.1 泛型类2.1.1 某种实际类型,重用性不好,Holder只能拥有A类型2.1.2 Object类型,类型太泛,可以容纳所有类型2.1.3 在创建的时候可以指定只可以容纳某种类型,此后只能容纳这种类型注意:基础类型无法作为类型参数,其封装类型可以2.2 泛型接口2.3 泛型方法3. 泛型擦除3.1 泛型只在编译期有效3.2 泛型内部无法获得泛型参数的有关信...

登峰小蚁 3065

java 泛型详解(普通泛型、 通配符、 泛型接口,泛型数组,泛型方法

Java代码Java代码Java代码Java代码Java代码Java代码Java代码。

2401_84619530的博客 1514

Java泛型的其他应用——泛型接口、泛型方法、泛型数组以及泛型的嵌套设置

学习目标 掌握泛型接口的使用 掌握泛型方法的定义的及使用 掌握泛型数组的使用 掌握泛型的嵌套设置 之前所有的操作都是在类中直接使用泛型操作的,那么,对于Java来说,也可以直接在接口中定义及使用泛型。 定义泛型接口 在JDK1.5之后,不仅仅可以声明泛型类,也可以声明泛型接口,声明泛型接口和声明泛型类的语法类似,也是在接口名称后面加上,如下格式所示: [访问权限]

1万+

Java【泛型】

Java的泛型说明

在下的博客 1467

java 泛型的默认值_java泛型

1.什么是泛型泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。泛型:泛型类 泛型接口 泛型方法作用:提高程序健壮性,简化代码泛型的默认值是Objectjdk 要1.5以上2.泛型定义/***泛型类*首先定义一个person的实体类 Person其中A代表的就是一个泛型,调用时可以自定义数据类型*/package com.temp;public class Per...

weixin_34246474的博客 1833

java中的泛型是什么_Java中泛型是什么?Java泛型的详细介绍

本篇文章给大家带来的内容是关于Java中泛型是什么?Java泛型的详细介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。一、什么是泛型?Java泛型设计原则:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常.泛型:把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型参数化类型:ArrayList中的E称为类型参数变量Arra...

weixin_29174013的博客 3474

java 泛型详解(普通泛型、 通配符、 泛型接口,泛型数组,泛型方法,泛型嵌套)

Java代码Java代码Java代码Java代码Java代码Java代码Java代码Java代码Java代码。

2501_90338778的博客 1538

【Java】关于Java泛型,为你做最全面的泛型介绍

泛型(Generics)是Java语言中的一个重要特性,它提供了类型安全和代码重用的机制。泛型起到的作用包括类型安全、代码重用、程序设计抽象、集合框架的增强、减少强制类型转换。在面向对象编程和设计模式中有广泛的应用。

✈ 正在努力 の 寒江(StudiousTiger) ✌ 呐 ✈ 1071

【Java】泛型深入

在刚刚,我们仅仅是使用泛型,那我能不能自己写一个类似于ArrayList带有泛型的类让别人去用呢,当然这必须是可以的。泛型可以写在类的后面,也可以写在方法上,还可以写在接口后。如果将泛型写在类的后面,那么这个类叫做泛型类在类名后面定义泛型,创建该类对象的时候,确定类型如果将泛型写在方法的后面,那么这个类叫做泛型方法在修饰符后面定义方法,调用该方法的时候,确定类型如果将泛型写在接口的后面,那么这个类叫做泛型接口在接口名后面定义泛型,有两种用法:① 实现类确定类型;② 实现类延续泛型。

qq_39921135的博客 1074
上一篇: Java写数据结构:队列
下一篇: Java--哈希Map
刘 大 望
博客等级 码龄2年 896粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值