为什么 JDK9 把 String 中 char 数组改成了 byte 数组?

JDK 9 中 String 的底层存储从 `char[]` 改为 `byte[]`:深入解析与实际应用 JDK 9 中String类的底层存储从char[]改为byte[],并引入了 Compact Strings 特性,显著优化了String类的性能和内存使用。通过根据字符串的内容选择合适的编码方式,减少了内存占用,提高了程序的执行效率。在实际编程中,这一改变对大量使用 Latin-1 字符串的应用产生了显著的内存优化和性能提升。希望通过本文的详细解释和代码示例,你已经对 JDK 9 中String类的底层存储变化有了更深入的理解。如果你有任何问题或需要进一步的解释,请随时提问! 阅读详情

大家好,我是鸭鸭!

此答案节选自鸭鸭最近弄的面试刷题神器面试鸭 ,更多大厂常问面试题,可以点击进行阅读哈!

目前这个面试刷题神器刚出,有网页和小程序双端可以使用!


回归面试题!为什么 JDK9 把 String 中 char 数组改成了 byte 数组?

这个题目的答案其实非常简单:这个操作主要是为了节省内存空间,提高内存利用率。

在 JDK 9 之前,String 类是基于 char[] 实现的,内部采用 UTF-16 编码,每个字符占用两个字节。

image.png

但是,如果当前的字符仅需一个字节的空间,这就造成了浪费。例如一些 Latin-1 字符用一个字节即可表示。

因此 JDK 9 做了优化采用 byte 数组来实现:

image.png

并引入了 coder 变量来标识编码方式(Latin-1 或 UTF-16)。对于大多数只包含 Latin-1 字符(即每个字符可以用一个字节表示)的字符串,内存使用量减半。

扩展 Latin1

Latin1 是国际标准编码 ISO-8859-1 的别名。Latin1 也是单字节编码,在 ASCII 编码的基础上,利用了 ASCII 未利用的最高位,扩充了 128 个字符,因此 Latin1 可以表示 256 个字符,并向下兼容 ASCII。

Latin1收录的字符除 ASCII 收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。欧元符号出现的比较晚,没有被收录在 ISO-8859-1 当中,在后来的修订版 ISO-8859-15 加入了欧元符号。

Latin1的编码范围是 0x00-0xFF,ASCII的编码范围是 0x00-0x7F。

Latin1 相对 ASCII 而言,较少被提及,其实 Latin1 的使用还是比较广泛的,比如 MySQL(8.0之前)的数据表存储默认编码就是 Latin1。

最后

最后再推荐下鸭鸭目前努力在做面试小程序神器面试鸭 ,已经有 3000 多道面试题目啦,欢迎大家来阅读!如果大家有不会的面试题,也可以在面试鸭内反馈!鸭鸭会第一时间为大家解答!

我是鸭鸭,我们下期见~

JDK 9中String的底层实现为何改为byte而非char? 在之前的Java版本中,String类的底层使用char数组来存储字符串的字符数据。然而,当处理非拉丁字符集,如中文、日文或韩文等时,一个字符可能需要多个char元素来表示,这导致了一些性能和内存占用上的问题。在JDK 9中,Java平台对于String的底层实现进行了一项重大的改变,将其内部的字符表示由char类型改为了byte类型。byte是一个字节,占用8位,相较于char的16位,它可以更高效地表示非拉丁字符集中的字符。需要注意的是,由于底层实现的改变,String类的API并没有发生任何变化。 阅读详情

相关推荐

STM32F407硬件IIC驱动OLED避坑实录:从‘不显示’到‘稳定刷屏’的完整调试过程

本文详细记录了使用STM32F407硬件IIC驱动OLED屏幕的完整调试过程,从初始的‘不显示’问题到最终实现‘稳定刷屏’。文章涵盖了硬件接线、I2C外设配置、常见问题排查及性能优化技巧,特别针对STM32标准库开发中的难点提供了实用解决方案,是嵌入式开发者驱动OLED屏幕的实用指南。

weixin_30315723的博客 303

关于String底层使用的是char数组还是byte数组以及一点String面试问题

结论是jdk1.8及以前String使用的是char数组,jdk1.9及以后使用的是byte数组。因为开发人员发现人们大多数使用的String还是拉丁字符而之前使用的char数组每一个char占用两个字节而拉丁字符只需要一个字节就可以存储,剩下的一个字节就浪费了,造成gc的更加频繁。因此在jdk9中将String底层的实现改为了byte数组。 在openjdk的开发日志中也是标注了这一改动以及改动的动机。 我们再去jdk中验证一下,先是jdk8 确实底层使用的是char数组。 而到了jdk9时,我们再看

qq_44507430的博客 1万+

neruolib全脑建模计算框架

neurolib 是一个用python编写的全脑建模计算框架,也是可扩展的、允许轻松实现自定义神经质量模型,能够在介观尺度上表示脑区平均活动。

Rootfyx的博客 1149

java9+的String底层实现为什么从char[]改成byte[]

在UTF-8编码中,ISO-8859-1编码的字符通常只需要使用一个字节来表示,但是对于某些ISO-8859-1字符,它们在UTF-8编码中需要使用多个字节来表示。对于ISO-8859-1编码的字符集中除了ASCII字符以外的字符,它们在UTF-8编码中需要使用多个字节来表示。相反地,当使用String类的toCharArray()方法或者其他获取字符串的char数组表示的方法时,String类会直接返回其内部维护的char数组,这个char数组就是使用UTF-16编码表示的字符序列。

洪晓鸿 1770

瑞芯微RK3506开发板Ethercat主站性能优化实战:从内核配置到微秒级延迟控制

本文详细介绍了在瑞芯微RK3506开发板上实现EtherCAT主站微秒级延迟控制的实战优化方案。核心在于部署Preempt-RT实时内核,并进行深度系统调优,包括CPU隔离、中断亲和性设置、内存锁定及电源管理调整。通过绕过Linux网络栈的专用驱动加载与配置,最终实现了稳定的高性能实时控制,满足工业自动化需求。

tcp8optimizer的博客 315

双脉冲测试中IGBT驱动电阻和驱动电容的研究

  在LTspice中没有双脉冲波形发生器,要做一个双脉冲的波形只能用电压源来进行特殊设置,不是很方便,为此我写了一个双脉冲波形发生器,有需要的可以下载。双脉冲波形发生器。   如下,该元器件可以自定义延迟时间Td,第一个脉冲宽度T1,第二个脉冲宽度T3,两个脉冲间隔T2,脉冲循环个数Ncycle以及高低电平Vhigh,Vlow。       IGBT开通时Rg的影响: 如果增大Rg: ①开通延...

gaoyong_wang的博客 8355

String介绍

string基本知识

m0_52449442的博客 625

Exposure Fusion

MertensTMO原理详解: 文章:2007年Exposure Fusion 论文链接:http://ntp-0.cs.ucl.ac.uk/staff/j.kautz/publications/exposure_fusion.pdf 论文代码:C版本:https://github.com/JawThrow/ExposureFusion python版本:https://github.com/lzocro/Exposure-Fusion matlab版本:https://github.com/Mericam

大长腿不解释 1653

科普文:JDK9新特性解读String底层char字符数组改成byte字节数组

2.String字符数组改字节数组,还增加了编码标志(ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character))标识用了什么编码;如果这个时候使用char[],一个char要占用两个byte,会占用双倍的内存空间。5.新版的String其实支持两个编码: Latin-1和UTF-16,如果String的内容中有汉字等超出Latin-1表示范围的字符。[]而不是char[]的原因是为了。

为无为,事无事,味无味。 1491

用Isaac Sim复现经典案例:手把手教你写Python脚本控制机械臂抓取(附避障算法调试心得)

本文详细介绍了如何使用NVIDIA Isaac Sim仿真系统复现机械臂抓取经典案例,包括Python脚本编写、避障算法调试等关键步骤。通过URDF模型导入、关节控制逻辑实现和RMPFlow避障配置等实战演示,帮助开发者快速掌握机器人仿真技术,特别分享了官方文档未提及的实用调试技巧和性能优化策略。

weixin_30632089的博客 408

基于LORA的双机通信的智能农业系统

通过LoRa模块与主机进行通信,监测环境中的温度、湿度、土壤湿度和光照强度等参数,并根据预设的自动控制逻辑或者手动指令控制继电器开关,从而调节风扇、加热器、水泵、喷雾器和灯光等设备,为植物提供适宜的生长环境。使用的Lora是大夏龙雀的感觉这个是我使用过的Lora里面最好用的,因为不用设置频道就可以直接透明传输,使用起来得心应手。就像两个单片机直接串口通信一样,缺点是异步串行,不能同时进行接收和发送。继电器灯亮模拟打开对应的风扇、水泵、灯、喷雾、加热。1.使用温度传感器测当前环境的温湿度。

ssjsjss的博客 1740

JDK9为何要将String的底层实现由char[]改成了byte[]?

来源:沉默王二如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由 char[] 优化为了 byte[] 来存储字符串内容,为什么要这样做呢?开门见山地说,从 char[] 到 byte[],最主要的目的是为了节省字符串占用的内存 。内存占用减少带来的另外一个好处,就是 GC 次数也会减少。一、为什么要优化 String 节省内存空间我们使用 ...

路人甲Java 339

使用ChatGPT工具阅读文献的实战教程

本文介绍核心内容为使用ChatGPT工具阅读文献,希望对学习和使用ChatGPT的同学们有所帮助。为了兼顾质量和速度,本专栏的更新频率为一周一到两更。 文章目录 1. 前言 2. 实战教程 2.1 下载工具并登录 2.2 提取文献中的关键信息

herosunly的博客 15万+

JDK9为何要将String的底层实现由char[]改成了byte[]?

程序员的成长之路互联网/程序员/技术/资料共享关注阅读本文大概需要 3.5 分钟。来自:沉默王二如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由char[]优化为了byte[]来存储字符串内容,为什么要这样做呢?开门见山地说,从char[]到byte[],最主要的目的是为了节省字符串占用的内存。内存占用减少带来的另外一个好...

良月柒 244

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

为什么JDK 9中把String的char[]改成了byte[]?

每当我们创建一个字符串时,如果它的所有字符都可以用单个字节(Latin-1)表示,那么将会在内部使用字节数组来保存一半所需的空间,但是如果有一个字符需要超过8位来表示,Java将继续使用UTF-16与字符数组。由于Java内部使用UTF-16,每个char占据两个字节,即使某些字符可以用一个字节(LATIN-1)表示,但是也仍然会占用两个字节。,其中第一位固定为0,后面的七位可以表示128个字符。那么,问题来了,所有字符串操作时,它如何区分到底用Latin-1还是UTF-16表示呢?

qq_38196449的博客 299

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

JDK9为何要将String的底层实现由char[]改成了byte[]

如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由char[]优化为了byte[]来存储字符串内容,为什么要这样做呢?开门见山地说,从char[]到byte[],最主要的目的是为了节省字符串占用的内存。内存占用减少带来的另外一个好处,就是 GC 次数也会减少。一、为什么要优化 String 节省内存空间我们使用jmap -hi...

hnjsjsac的博客 263

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

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

在jdk9开始为啥要把char数组改成字节数组

因为char数组每个字符占2个字节,而String对应的每个字符占1个字节,那么浪费一半的空间。所以替换成了字节数组。

qq_21277357的博客 118

Java面试必备:为什么JDK9中将String的char数组改为byte数组?

在JDK9中,Oracle对String类的内部实现做了一个重大改变:将原本的`char[]`存储改为`byte[]`存储。这一改变看似简单,却蕴含着深刻的设计优化思想。本文将深入探讨这一改变的原因、实现机制以及带来的好处。

qq_58299462的博客 951

jdk9为何要将String的底层实现由char[]改成了byte[]

先说结论:出于节省String占用jvm的内存空间。 优化String节省jvm内存空间的必要性 (1)调查统计发现一个java系统,堆里面存活最多的对象之一就是String对象,所以优化String的占用空间是很有意义的,因为String是实际开发中使用最频繁的类。否则,你去优化一个平时根本不怎么用到的类,那么就很鸡肋了。 上图是基于java8运行的spring boot系统对象数量的快照,我们可以看到String对象有82039个,占用了1968936字节的内存,占用内存排在第5位。 这里注意的是ja

tc979907461的博客 2110

JDK9 为何要将String的底层实现由char[]改成了byte[]

没得办法,和char[]表示String没什么区别,即使现在是byte[]来表示String,还是得乖乖用UTF16编码,和优化之前一样,没节省空间(LATIN1编码集支持的字符有限,其中就不支持中文字符,因此才保留了UTF16兜底)。所以使用char[]来表示String就导致了即使String中的字符单个字节就能表示,还是得占用了两个字节,而实际开发中使用频率最高的却是。的对象之一就是String对象,所以优化String的占用空间是很有意义的,因为String是实际开发中。

小鲁蛋的博客 1157

Java 9 为何要将String的底层实现由char[]改成了byte[]?

如果你不是 Java8 的钉子户,你应该早就发现了:String 类的源码已经由 char[] 优化为了 byte[] 来存储字符串内容,为什么要这样做呢?开门见山地说,从 char[] 到 byte[],最主要的目的是为了节省字符串占用的内存 。内存占用减少带来的另外一个好处,就是 GC 次数也会减少。为什么要优化 String 节省内存空间我们使用 jmap -his...

程序猿DD 1488

Java9为何将String的底层实现由char[ ]改成了byte[ ]

Java9为何将String的底层实现由char[ ]改成了byte[ ]

m0_62335720的博客 811

JDK9到底为什么要将String的底层实现由char「」改成了byte「」

但是在 Java 中,一个字符(char)就是 2 个字节,占 4 个字节的字符,在 Java 里也是用两个 char 来存储的,而String的各种操作,都是以Java的字符(char)为单位的,charAt是取得第几个char,subString取的也是第几个到第几个char组成的子串,甚至length返回的都是char的个数。也就是说,从 char[] 到 byte[],中文是两个字节,纯英文是一个字节,在此之前呢,中文是两个字节,英文也是两个字节。

AS011x的博客 584
上一篇: Spring MVC 中的视图解析器有什么作用?
下一篇: 常见八股面试题:用过 MySQL 读写分离吗?怎么做的?
「已注销」
博客等级 码龄6年 836粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值