Java中的泛型 (进阶篇)

Java泛型总结(2)进阶篇 NULL 博文链接:https://fantaxy025025.iteye.com/blog/2213815 立即下载

这一篇是关于泛型的进阶知识,如果有对泛型不了解的小伙伴可以移步第一篇基础版文章

Java中的泛型 (基础版)

 本文主要介绍类型通配符的使用、泛型的继承以及类型擦除的知识点。

目录

类型通配符

上界通配符、下界通配符

上界通配符

下界通配符

限制通配符在TreeSet中的应用

类型擦除

无限制类型擦除

添加上界的类型擦除

添加下界的类型擦除

桥方法


类型通配符

当我们想实现某个功能时,可能会出现这种情况:

这里实现一个简单的打印数字列表的方法

// 打印Integer类型的List
    public void showInteger(List<Integer> values) {
        for (Integer i : values) {
            System.out.println(i);
        }
    }

过了一会儿我又想实现一个打印Double类型列表的方法,于是:

// 打印Double类型的List
    public void showDouble(List<Double> values) {
        for (Double i : values) {
            System.out.println(i);
        }
    }

在过一会儿可能又想实现一个打印Long类型的列表,这样一来就光做了重复的工作。

这样就引入了类型通配符:

public void showNumber(List<?> values) {
        for (Object i : values) {
            System.out.println(i);
        }
    }

 在这里,使用了List<?> 当形参的类型,表示List类型是一个通配类型,实现了不管什么类型的列表,传给这个方法就可以实现打印的功能。

上界通配符、下界通配符

这一部分稍难理解

上界通配符

先说上界通配符:定义为<? extends T>, " ? " 刚才讲到了,是一个通配符,extends 也可以理解,是继承,而" T "在这里可以是泛型,也可以是具体的类型,比如Number。什么意思,通配符继承自一个类型。那么就可以理解成给这个通配符加了一个限制:只能是T类型或其子类,那不就是给通配符规定了一个上界为“ T ”吗。

如果还是不理解,那么举个例子:现在有一个盘子,如果在不加限制条件的情况下是不是盘子里什么都能装,没错,这就是不加限制的通配符“  ? ”。 那么现在我给盘子加一个限制说,这个盘子只能装水果,那么我的这个盘子里是不是就只能装苹果、香蕉等等属于水果范畴的东西,这就好加了限制条件的通配符:<? extends fruit>。

理解了什么是上界通配符后,我们来看一下怎么使用:

开头的例子中

public void showNumber(List<?> values) {
        for (Object i : values) {
            System.out.println(i);
        }
    }

我们发现一个问题,在遍历的时候居然用Object给我接收列表中的变量,我们知道,要求是打印数字列表的方法,不管是Integer、Double还是Long类型,他们都继承自Number对象,那么我们可不可以给通配符加一个限制条件<? extends Number> 用来表示我只能装来自Number对象的数据。

于是代码改为:

public  void showNumber(List<? extends Number> values) {
        for (Number i : values) {
            System.out.println(i);
        }
    }

这样的话,我们取到的就是Number的数据了,因为我知道这个List装的都是Number及其子类。

好了,这个问题解决完了,还有下一个问题,也是比较难理解的问题:

我现在想实现往列表里添加元素,于是有了:

public List<? extends Number> addList(List<? extends Number> list) {
        list.add(1);  // 编译异常
        return list;
    }

结果发现:哎呦我去,添加的时候编译异常了,要知道我这List里装的可都是Number或其子类,按理来说应该能装进去啊。

我们思考这样一个问题,之前我们说 <? extends Number> 代指的意思是限制了一个上界,所以说这个List可以是List<Integer> 或 List<Double> 或 List<Number> ,这样一来如果这是List<Double>那 是不是就不能装Integer类型的数据了,这也是上界通配符的一种特性:能用Number来读,但不能往里面写数据。后面的下界通配符正好相反:只能写,不能用Number读。真的什么都不能写了吗?其实我们可以通过反射去绕过类型检查来添加元素。

下界通配符

下界通配符,语法为 <? super T> 这里就不过多解释了,就是为通配符限制了一个下界,也就是说,通配符的类型只能是T及其父类类型。下界通配符就是用来写入数据了。

举例子:有一家宠物店有宠物笼子,猫笼子,和布偶猫笼子,现在有一只布偶猫,是不是把它放入哪个笼子都说得过去,也就是 <? super 布偶猫笼子>, 所以这样就可以写入数据了

public List<? super Number> addList(List<? super Number> list) {
        list.add(1);
        list.add(1.0);
        list.add(1.0f);
        return list;
    }

那读入数据可不可以呢,让我们实验一下:

我们用Number来接收List里的变量

public void showList(List<? super Number> list) {
        for (Number number : list) {  // 编译错误
            System.out.println(number);
        }
    }

我们发现还是报了一个编译错误,因为List里装的都是Number或其父类,无法确定就是Number类型。所以这里只能用Object类型来接收。

正确写法:

public void showList(List<? super Number> list) {
        for (Object o: list) {  // 编译错误
            System.out.println(number);
        }
    }

限制通配符在TreeSet中的应用

在TreeSet的构造方法中也使用了上下界通配符的方式

假设我们现在有三个类A、B、C,C继承B,B继承A

在TreeSet中有这样一个构造方法:

要求传入一个集合

        Set<A> setA = new HashSet<>();
        Set<B> setB = new HashSet<>();
        Set<C> setC = new HashSet<>();
        
        TreeSet<B> treeSet1 = new TreeSet<>(setA); // 报错
        TreeSet<B> treeSet2 = new TreeSet<>(setB);
        TreeSet<B> treeSet3 = new TreeSet<>(setC);

不难看出,当我们定义了B泛型的TreeSet,相应的构造方法中的泛型E就变为了B类型,然后可以传入B及其子类的Set对象进行构造

还有一个构造函数:

要求的是传入一个比较器

        Comparator<A> comparatorA = new ComparatorA();
        Comparator<B> comparatorB = new ComparatorB();
        Comparator<C> comparatorC = new ComparatorC();

        TreeSet<B> treeSet1 = new TreeSet<>(comparatorA);
        TreeSet<B> treeSet2 = new TreeSet<>(comparatorB);
        TreeSet<B> treeSet3 = new TreeSet<>(comparatorC); // 报错

这里就变为了B的子类C不能作为比较器进行传参,因为需要传B及其父类

类型擦除

基础篇中提到,泛型是JDK5后才提出的,我们知道,只要是后期出现的一种语法就会有与之前版本兼容的问题,那么泛型是如何解决兼容性问题的呢?

现在有这样一段代码:

        List<Integer> list1 = new ArrayList<>();
        List<Double> list2 = new ArrayList<>();

        System.out.println(list1.getClass() == list2.getClass());

分别给List加Integer 和 Double 泛型,然后检验他们的类是否相同

结果出人意料,返回结果是true

为什么会这样呢,这里明确定义了两种不同的泛型,为什么还会是同一个类呢。

用ASM插件观察一下编译后的字节码文件

 我们发现,我们所定义的这两个局部变量都出自一个类,而先前定义的泛型也变为了注释的形式

说明一点:JDK在进行编译的时候,把泛型类型擦除掉了。

其实我们也能想到,从一开始泛型就是为类定义了一种规范,如果不按照规范进行书写,在编译时就会编译异常。用List来解释就是:在原来的List中不加泛型的话可能什么类型的数据都能够加入List中,相当于存储Object类型了,但是如果加泛型呢,依然是存储Object类型,不过如果加入的不是我想要的数据类型就会编译异常,这样一来List中就自然存放我想要的数据类型了,而泛型在后期也会被擦除掉。

下面就深入探讨一下类型擦除的机理

无限制类型擦除

这里我定义了一个水果盘子,没有加任何限制

public class FruitPlate<T> {
    private List<T> fruits;

    public void addFruit(T fruit) { // 添加
        fruits.add(fruit);
    }

    public T getFruit(int index) {  // 获取
        return fruits.get(index);
    }

}

如果我们没有给泛型加任何限制,那么在编译之后,泛型T的类型是什么样子的呢?这里为了方便,我直接用ASM插件查看编译后的字节码文件,当然也可使用反射在运行中查看参数类型

在编译后的字节码文件中,我们发现添加方法的形参上变为了Object类型,所以说泛型在不加任何限制时被擦除会被替代为Object类型。

添加上界的类型擦除

那么我为他添加一个上界呢

假设我定义了一个水果类型

public class Fruit {
}

让水果盘子的泛型继承水果类型,就是让水果盘子只能装水果:

public class FruitPlate<T extends Fruit> {
    private List<T> fruits;

    public void addFruit(T fruit) {
        fruits.add(fruit);
    }

    public T getFruit(int index) {
        return fruits.get(index);
    }

}

再进行编译:

就发现原来的泛型被擦除成了水果类型了,原因是:我们为这个泛型规定了一个上界,所以这个上界就已经可以包含所有的类型参数了。

添加下界的类型擦除

下界就很清楚了,因为规定的是下界,一定是Object才能包含所有的类型参数。所以擦除后变为Object类型,这里不再演示了。

桥方法

定义:是 Java 泛型实现中的一种补偿机制,通过自动生成中间方法解决类型擦除后的多态冲突,确保泛型类和接口的行为符合预期

什么是多态冲突,多态我们都知道,一个接口底下可以有多个实现该接口的实现类,我们下面模拟解释什么是类型擦除后的多态冲突问题。

 定义一个泛型接口:

// 泛型接口
interface Comparable<T> {
    int compareTo(T o);
}

再定义一个实现类:

// 具体实现类(擦除后 T 变为 Object)
class MyInteger implements Comparable<Integer> {
    @Override
    public int compareTo(Integer o) {
        return 0;
    }
}

注意这里我们实现类的泛型规定为Integer类型,所以它的实现方法中就是Integer类型。我们刚才讲到类型擦除的时候提到,无限制的类型擦除都会被替换成Object类型,所以在类型擦除后原来的接口方法应该是这样的:

    public int compareTo(Object o);// 原接口方法泛型被替换为Object

根据方法重载我们知道,参数类型不同,那么方法不同,这两个方法不是同一个方法又是如何调用的呢。

为了解决这样的冲突问题,JDK则引入了桥方法的概念:

在编译时,JDK会根据继承关系、方法签名以及泛型类型擦除后的冲突情况,从而决定是否需要生成桥方法,具体的桥方法如下:

 // 编译器生成的桥方法
    public int compareTo(Object o) {
        return compareTo((Integer) o); // 类型转换并调用实际方法
    }

此方法是JDK为我们自动生成的方法,不需要自己实现。所以这个方法的执行顺序是:先检查接口方法,然后去子类中调用桥方法,最后通过桥方法调用实现方法。

多臂老虎机——入门强化学习 多臂老虎机(Multi-Armed Bandit,MAB)问题是强化学习的经典入门例子,也是理解探索与利用(exploration-exploitation)平衡的重要案例。 阅读详情

相关推荐

《点亮创新灯塔!AI应用架构师与中小学初等教育AI智能体,共筑智能化教育辅助创新灯塔》

中小学AI智能体,是基于AI技术,能感知教育场景、理解教育规律、辅助教师教学和学生学习的智能系统。做老师“做不了”的事:比如5分钟批改45本作业,精准统计每个学生的易错点;做老师“做不好”的事:比如根据学生的学习风格(视觉/听觉/动觉)推荐个性化内容;绝不做老师“该做的事”:比如情感交流、价值观引导、创意教学设计——这些“人的温度”,AI永远无法替代。我是林宇,资深AI应用架构师,专注教育AI领域8年,参与过10多个中小学AI智能体项目,曾为北京、上海、深圳等城市的100多所学校提供AI教育解决方案。

Java大师兄的博客 433

JAVA进阶-——泛型

目录 前言 一、泛型是什么? 二、为什么我们要使用泛型? 三、泛型的使用 3.1 泛型类 3.2 泛型方法 3.3 泛型接口 四、通配符与上下界 五、泛型在虚拟机中是如何实现的? 总结 前言 接下来一段时间,本人会将近期所看到的学到的一些知识分享在优快云上,欢迎各位大神前来交流、指教,首先会从JAVA开始,毕竟作为安卓开发工程师,JAVA是基础,后续也会更新一些安卓方面的内容。第一篇博客,是关于JAVA中的泛型。文章中的图表、代码均为原创,如需转载,请注明出处。 一、泛型是什么?

bugmaker的博客 627

Power Peofiler Kit II 的功耗工具简单上手入门使用

这里仅仅简单记录一下Power Peofiler Kit II 的简单使用,使之快速上手使用起来。官网说明:https://www.nordicsemi.cn/tools/ppk2/上位机软件默认你已经下载好了。

久新的博客 2180

【Java】泛型

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《Java编程思想》对泛型的介绍。泛型是在JDK1.5引入的新的语法,通俗讲,泛型:**就是适用于许多许多类型。**从代码上讲,就是对类型实现了参数化上界和下界一个是只能读取不能写入 一个是只能写入不能读取 该如何理解呢?这张图代表着通配符下界 只要是Fruit的子类都可以传入。

m0_72670269的博客 811

双向晶闸管交流调压基础知识及Multisim电路仿真

本文介绍了双向晶闸管交流调压电路的工作原理及应用。该电路由双向晶闸管、RC移相电路和双向触发二极管组成,通过调节电位器改变触发角实现电压调节。当电位器阻值减小时,触发角减小,输出电压升高;阻值增大时,触发角增大,输出电压降低。Multisim仿真展示了不同电位器档位下的波形特征:0%档位时全导通,50%档位时半导通,100%档位时基本关断。该电路结构简单、调节平滑,广泛应用于调光、调速等场合,但会产生谐波干扰。

XU157303764的博客 837

2021秋-北邮计算机导论期末考试(BUPT)

2021秋-北邮计算机导论期末考试(BUPT) 难度较低适合新手练习

weixin_73985779的博客 1497

Java泛型进阶学习

java泛型详解

keepstrivingchy的博客 525

【Bug已解决】Codex 报错 MCP client for context7 failed to start: program not found 解决方案

方案适用场景推荐指数改用绝对路径Windows 上最常见、最有效的解决方式⭐⭐⭐⭐⭐提前全局安装避免依赖 npx减少运行时网络下载的不确定性⭐⭐⭐⭐使用 .cmd 后缀Windows 平台快速尝试⭐⭐⭐⭐开启调试日志需要更精确定位失败原因⭐⭐⭐⭐统一封装启动脚本需要跨平台兼容多个 MCP 服务⭐⭐⭐报错的本质是Codex 启动 MCP 子进程时,无法正确定位配置文件中写的简写命令名对应的可执行文件,尤其容易发生在 Windows 平台上使用npx这类简写命令的场景。

一键难忘的博客 5814

Java 泛型进阶

一般的类和方法,只能使用具体的类型要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。-----来源《Java编程思想》对泛型的介绍。泛型是在JDK1.5。? 用于在泛型的使用,即为通配符虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类

weixin_73616913的博客 984

python爬取银行年报2

python爬取公司年报(巨潮资讯网)

bboysteed的博客 4730

电子元器件选型与实战应用—01 电阻选型

大家好, 我是记得诚。这是《电子元器件选型与实战应用》专栏的第一篇文章,今天的主角是电阻,在每一个电子产品中,都少不了电阻的身影,其重要性不言而喻。

记得诚 3536

[进阶]Java:泛型深入、自定义泛型

String[] names = {"鸟儿","小鸟","大鸟"};例如代码中,extends Car 后,狗类就无法进来了。

m0_68783582的博客 224

神经影像和人类基因组关联分析的实践过程

现代全脑转录图谱为研究脑组织的分子相关性提供了前所未有的机会,可以使用无创神经成像进行量化。然而,将神经影像学数据与转录组测量相结合并不是直截了当的,需要仔细考虑才能做出有效的推断。在本文中,我们回顾了最近的研究工作,探讨了不同的方法选择如何影响成像转录组学分析的三个主要阶段,包括1)转录图谱数据的处理;2)将转录测量与独立衍生的神经影像学表型相关联;3)通过基因富集分析评估鉴定的关联的功能意义。我们的目标是为这个快速发展的领域促进标准化和可复制方法的发展。

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 2201

Java进阶篇之泛型

泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数一提到参数,最熟悉的就是定义方法时如果有形参,调用此方法时就要传递实参,那么参数化类型该怎么来理解呢?顾名思义,参数化类型就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法和泛型接口:指定一种类型的格式,这里的类型可以看成是形参。

一以贯之的努力 不得懈怠的人生 840

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

java集合进阶篇-《泛型》

泛型对于我来说又是一个新的名词,在其他语言中或许也有,只是我可能没学到。接触一个新的东西学习起来是比较吃力的,但收获也挺多的,毕竟是一个新的知识点。有些不理解的地方希望各位大佬能够多加点评。Java中的泛型是一种在编译时检查类型安全性的特性,它允许程序员编写出更加类型安全的代码,同时避免了运行时类型转换错误。泛型是在Java SE 5.0版本中引入的,它使得代码更易于阅读和维护,并且减少了强制类型转换的需要。

欢迎大家一起讨论交流 1102

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java进阶篇01、泛型

规定了泛型下界为Fruit,所以说里面存取的元素是Fruit或者是Fruit的父类,所以我们在setData方法中可以传入Fruit或者是Fruit子类的对象,同样可以理解为向上转型是安全的;同理getData方法只能确定取出的元素是Fruit或者是Fruit的父类,但是并不能确认是哪个父类,又因为Object是所有类的父类,所以用Object接受肯定是没有问题的。通配符没有进行限制,所以不能用setData方法操作任何对象,又因为Object是所有类的父类,所以使用Object接受是没问题的。

2501_90253379的博客 533

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Java进阶篇--泛型

此外,Java 泛型的类型参数只能是类类型(包括 Class、接口类型或枚举类型),不能是数组类型或函数类型。这样,在 MyBox 类中,我们可以直接使用 Integer 作为类型参数,而不必重新定义一个新的类型参数。你可以在类的定义中使用 T 来表示泛型,然后在方法中使用 T 来表示任何类型的对象。在上述代码中,我们定义了一个泛型方法 getFirst,它接受一个 List 类型的参数,并返回一个 T 类型的对象。泛型的基本语法是在类、接口或方法名的后面加上尖括号(< >),并在其中定义类型参数。

m0_74293254的博客 1140

【JAVA学习之路 | 进阶篇】<-泛型->

(2). java.lang.Comparable接口和java.util.Comparator接口,是用于比较对象大小的接口.这两个接口只是限制了当一个对象大于另一个对象时返回正整数,等于返回0,否则返回负整数.但由于并不确定是什么类型的对象比较大小.jdk5.0之前只能用Object类型表示,即麻烦(可能需要强制类型转换)又不安全(可能比较的两个对象并不是同一类型).故jdk5.0给它们增加了泛型.(1). 我们在声明完自定义泛型类后,可以在类的内部(如属性,构造器,方法)使用类的泛型.

2301_80912559的博客 695

Java 第31天 高级进阶篇 Java泛型

一、泛型的设计背景: 方式一:集合中 ArraysList 为例: 方式二:在集合泛型中HashMap为例 二、自定义泛型类学习 package Com.Work_ZQ3; /** 自定义 泛型类 @param */ public class Order { String name; int orderId; // 类的內部結構可以使用泛型. T orderT; public Order() { } public Order(String name, int orderId, T orde.

禧年 206

2021Java进阶篇(二)Collection和泛型

2021Java进阶篇(二)Collection和泛型 进阶篇第二篇来了,希望对大家能够有帮助~~~ 文章目录2021Java进阶篇(二)Collection和泛型前言一、Collection集合1.1 概述1.2 Collection接口1.3 Collection 常用方法二、Iterator迭代器2.1 Iterator 接口2.2 常用方法2.3 迭代器的实现原理2.4 增强for三、泛型3.1 **概述**3.2 定义和使用含有泛型的类3.2.1 定义一个含有泛型的类3.2.2 定义一个含有泛

her_mia的博客 645

Java中的泛型-进阶篇

qq_28359883的博客 156

Java 基础进阶篇(十):泛型与可变参数

一、泛型概述 二、泛型的定义 2.1 泛型类 2.2 泛型方法 2.3 泛型接口 三、泛型深入 3.1 泛型通配符 3.2 泛型上下限 3.3 举例:定义一个 “所有车量进行比赛” 的方法

秀岩的博客 1700

Java语言程序设计-进阶篇(二)泛型

泛型类是JDK1.5之后增加的特性,可以使程序更加可靠 1.定义泛型 定义泛型类时,放在类名之后。定义泛型方法时,放在返回值之前。 2.原始类型与泛型消除 Comparable a = new Comparable();是原始类型,相当于Comparable a = new Comparable();泛型在JVM中实际上是转换成原始类型来处理的,目的是为了向后兼容,这种转换就称为泛型消除。

duan_2018的博客 337

java中的泛型(二)——泛型接口以及泛型方法

本文简要介绍了泛型接口以及泛型方法的使用

qq_59750520的博客 4701

Java中的泛型

使用Java的小伙伴,对于Java的一些高级特性一定再熟悉不过了,例如集合、反射、泛型、注解等等,这些可以说我们在平时开发中是经常使用到的,尤其是集合,基本是只要写代码没有用不到的,今天我们先来谈谈泛型。 1. 定义 在了解一个事物之前,我们必定要先知道他的定义,所以我们就从定义开始,去一步一步揭开泛型的神秘面纱。 # 泛型(generics) 他是 JDK5 中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。泛型的本质就是参数化类型,也就

LHH201016的博客 4843

Java 中的泛型详解

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错。那参数化类型是什么?以方法的定义为例,在方法定义时,将方法签名中的形参的数据类型也设置为参数(也可称之为类型参数),在调用该方法时再从外部传入一个具体的数据类型和变量。

XuChaofafa的博客 1704
上一篇: Java中的泛型 (基础版)
下一篇: Java中的注解与反射
pillow_mycode
博客等级 码龄3年 34粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值