返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java--包装类的学习
  • 539
分享到

Java--包装类的学习

java学习笔记开发语言 2023-08-16 14:08:32 539人浏览 安东尼
摘要

本文介绍了Java中的包装类-- 什么是包装类 ,包装类和基本数据类型之间的关系转换 --装箱与拆箱,包装类的valueOf和XXValue以及构造方法的总结 , 自动装箱和拆箱以及触发的情况 , 包装类内里的缓存机制, 包装类一些相关

本文介绍了Java中的包装类-- 什么是包装类 ,包装类和基本数据类型之间的关系转换 --装箱与拆箱,包装类的valueOf和XXValue以及构造方法的总结 , 自动装箱和拆箱以及触发的情况 , 包装类内里的缓存机制, 包装类一些相关练习题和面试题

一.包装类

在java中有基本数据类型 --四类八种 有引用数据类型
相比基本数据类型来说,它可以用来定义数据的基本类型,也可以用来定义存放对应基本数据的空间类型

而java是一种纯面向对象编程语言, 一切皆对象, 显然基本数据类型不符合这一设定,因为它仅仅是用来描述一个数据的类型. 因此,包装类由此诞生…

1. 什么是包装类?

包装类是一种特殊的类,它是针对现有的基本数据类型延伸拓展的类类型
包装类即是对应着各种基本数据类型进行包装后产生的引用数据类型 ,
是基本数据类型的plus版本

通过类来描述基本数据, 将数据和操作数据的方法进行有机结合, 不仅可以描述一个基本数据类型,还能描述这个类型的一些相关属性(最大值,最小值…) 以及对应这个基本数据类型相关的方法(valueOf 将字符串类型转换成此基本数据类型)

拿Integer为例 , int对应的包装类是Integer ,它内部的value存放的就是对应的基本数据 ,而还额外有很多静态属性 比如 int的最大值 最小值 Size:int占多少bit位等…
在这里插入图片描述

2.基本数据类型对应的包装类

基本数据类型有四类 8种, 对应包装类也有8种

基本数据类型包装类
boolean (未定义)Boolean
byte(1字节)Byte
char (2字节)Character
short(2字节)Short
int(4字节)Integer
long(8字节)Long
float(4字节)Float
double(8字节)Double

除了 Integer 和 Character, 其余基本类型的包装类都是首字母大写。

3.基本数据类型和包装类类型之间的转换

每个基本数据类型都有其对应的包装类, java中用来表示更具体完善的类型会用包装类,但是在一些运算 ,比较或者简单存储时会用到基本数据类型,而二者间可以进行相应的转换

①.装箱和拆箱

装箱:将基本数据类型转换为对应包装类
拆箱:将包装类转换为对应基本数据类型

int i = 10; // 基本数据类型 --int 定义的整形空间i 存放整形常量10// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中//装箱操作: 将一个基本类型的数据(int) 放到对应的包装类对象(Integer)中Integer ii = Integer.valueOf(i);//调用Integer.valueOf方法传基本数据类型的数据(常量或者变量) 将其转换成Integer对象Integer ij = new Integer(i);// 创建Integer对象 构造时提供对应的基本数据// 拆箱操作:将 包装类对象(Integer)对象中的值取出放到一个基本数据类型(int) 变量中int j = ii.intValue();// ii是Integer对象 内有成员方法intValue 即返回此对象内存储的基本数据

int和Integer就好像大古和迪迦奥特曼
大古是一个普通人,它能做的事相对较少, 而迪迦是奥特曼拥有更多的能力

装箱即是大古变身为迪迦…
迪迦内部仍然是大古,但是它具备了很多属性和行为
(大古是普通人,因为其能力小,一些大型工作就难以胜任 某些特殊场景:打怪兽 等 需要将大古变身为迪迦)
用包装类适用于某些较大的复杂的工作

拆箱即是迪迦变回大古…
变回大古后,便是一个普通人,不再具备那些额外的属性和能力
在日常生活中 迪迦相比大古各方面都比较"重",占据的资源也大,
用基本数据类型更完成适合日常简单的一些工作

②.各个包装类的valueOf和XXValue方法和构造方法

因为基本数据类型和包装类有8种,故每个一个包装类里都有其自己的valueOf方法和XXValue方法可以将对应的基本数据类型和包装类之间进行转换…
XX表示基本数据类型中的某种

Integer:
在这里插入图片描述
Integer的valueOf主要有两个
一个是将字符串数据转换成对应的包装类数据(方便将字符串内容转换成指定类型数据)
一个是将对应的基本数据类型转换成对应的包装类 (如Integer包装类的valueOf提供的是将int转换成Integer)

而XXValue方法除了BooleanValue和CharValue 其他的基本数据类型转换都有, 表示的含义就是将Integer包装类对象里的int数据拆箱成对应XX类型的数据
Character:
在这里插入图片描述
提供的valueOf方法只有 对char进行操作的一个方法, 因为其对应的只是一个字符,字符串是有n个字符的集合,不存在n个字符转变成一个字符没有对String进行操作的

XXvalue也只有一个将Character转换成char的 charValue方法,因为char是字符类型数据,和其他的基本类型数据不同,它是一种由整数特殊对应的字符数据
它可以表示英文字符 中文字符
在这里插入图片描述
英文字符用Ascll码(-128~127的整数)表示 ,中文字符根据不同的字符编码表示(有的是两个字节对应一个中文字符 有的是三个), 字符类型本意就是表示字符的, 故只有转换成对应的char类型的XXValue方法 ,如果需要转成整数可以进行强转

Boolean:
在这里插入图片描述
Boolean是boolean布尔类型对应的包装类 .它表示的只有true和false两种情况, valueOf提供的将boolean进行转换 和将String类型数据进行转换(字符串转换时 字符串的值只能是"true"or"false")

XXValue只有booleanValue ,因为布尔类型数据是特殊的,和其他类型数据没有关联

Byte&Short&Integer&Long&Float&Double:
在这里插入图片描述
以Short为例, Byte Short Integer Long Float Double这六个包装类里提供的valueOf都是两个 ,一个是将字符串转换成对应的包装类 , 一个是将对应的基本数据类型转换成包装类

XXValue都是6个 就是将此包装类进行转换成这六个包装类对应的基本数据类型

关于八个包装类的构造方法 ,Character 只有一种char类型的构造方法
Float 有 float double String三种构造方法 ,其他的包装类都提供的是对应基本数据类型 和String 两种构造方法 在手动装箱的时候要注意一下…

③.自动装箱和自动拆箱

上述装箱拆箱的操作过于繁琐,本质上就是想实现基本数据类型和包装类类型之间的快速转换
装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

int i = 10; // 基本数据Integer ii = i; // 自动装箱Integer ij = (Integer)i; // 自动装箱int j = ii; // 自动拆箱int k = (int)ii; // 自动拆箱float f=(float) ii;

上述代码即实现了自动装箱和自动拆箱

主要通过 = 赋值运算符 直接将基本数据赋值给包装类引用 (自动装箱)
将包装类对象赋值给基本数据类型定义的空间(自动拆箱)

注意:自动装箱和自动拆箱 两边的类型要对应 (不能出现不符合内部设计出现类型完全不匹配的情况)

自动装箱和自动拆箱是怎么完成的呢?
在命令提示符中 进入找到编译运行的字节码文件所在的目录 ,输入java -c 字节码文件 后进行反汇编
在这里插入图片描述
在这里插入图片描述

通过反汇编可以看到:

自动装箱操作在底层实际是调用了valueOf方法,在底层帮你进行的装箱, 将基本数据类型转换成了对应的包装类 ,不同的包装类调用的valueOf方法的参数是当前包装类对应的基本数据类型
如int装箱 调用的valueOf(int)方法

自动拆箱操作也是在底层调用了intValue方法,将Integer包装类转换成了int基本数据类型的数据, 不同的包装类进行拆箱调用的是不同的XXValue方法
如Integer拆箱 为int 调用 IntValue方法

关于自动装箱自动拆箱的类型检测:
在自动装箱时会进行类型是否匹配的检测 , 包装类类型和基本数据类型之间进行赋值 必须得类型对应 如Integer i=1; Float=1.0L; Long l =1L;两边的类型要对应,否则就会编译报错…
Long l=1; // 此时 整形1对应包装类Long是类型不对应的 是会编译报错的,除非强转

**在自动拆箱时,类型匹配会适当放宽, 自动拆箱时会转换为包装类对应的基本数据类型,此时赋值给某个变量 ,这个变量不需要类型完全匹配, 精度大于等于赋值的数据都可以,编译器会进行隐式类型转换,如果精度不匹配则需要显示强转 **
因此可以看到 int k=(int)ii; 这个语句时,(int)编译器会提示:Casting ‘ii’ to ‘int’ is redundant (将ii 强转为int 是多余的)
在拆箱时,本身ii就是int类型 不用再强转 , 如果是k是byte类型的 则要byte k=(buye)ii; 或者long k =ii ; 都是可以的
包装类类型是不能直接强转为基本数据类型的,基本数据类型也不能直接强转为包装类类型

包装类之间进行赋值操作必须得类型匹配不会存在隐式类型转换 也不能强转 如 Integer i= new Byte(“1”); // 类型不匹配 编译报错

基本数据类型之间的赋值操作存在隐式类型转换和强转…

④.触发自动装箱/拆箱的情况

在java中引入自动装箱/拆箱本质是为了书写代码的方便,但是其中会有一些小细节,不注意就会导致一些错误~

以下是博主整理的一些情况

自动装箱:
1.在使用直接赋值操作时 包装类类型 变量 = 基本数据类型;
2.在进行方法传参时 形参是包装类类型 实参是基本数据类型
3.在方法返回值时 返回类型是包装类类型 返回的值是基本数据类型

注意: Object类型的引用变量 接收基本数剧类型 发生自动装箱, 在方法传参和返回值处 同样适用
因为Object本身是所有类的父类包括包装类 Object obj =1L时, 编译器会进行检测, 最后会将1L包装成Long对象 赋给obj

自动拆箱:
1.两个包装类或者基本数据进行算数运算操作时 (+ - * / % | & ^ …)
2.两个包装类或者包装类数据和基本数据类型进行比较运算操作时 ( > < …) ==有特殊情况
3.包装类对象进行强转操作会拆箱为基本数据类型再强转

注意:
1.进行上述拆箱操作时需要类型对应, 可以Integer 数据和Long类型数据进行运算,但是要注意产生的结果会隐式转换为高精度类型(需要根据实际情况进行强转)但是不能类型不对应 比如: Integer数据和Boolean数据(因为boolean没有确切的数字 只是表示真假 )
但是Integer 和Character进行运算是可以的, 因为对应的char类型数据本质上就是一个整数…
一个包装类和一个基本数据进行操作和上述同样…

包装类可以通过强转来拆箱成基本数据类型, 但是基本数据类型不能通过强转包装类进行装箱

当两个包装类类型进行比较运算时, 如果判断是否相等则不能使用==等号, 因为编译器会默认当做是两个对象进行比较(比较的是对象的地址)!需要比较是否相等需要调用包装类重写的equals方法
比较大于小于等操作会自动拆箱,并且也提供了比较大小的方法CompareTo
(当一个包装类和一个基本数据类型等号号比较 包装类会进行拆箱)

一个包装类和基本数据类型进行比较相等 或者大小时,包装类会进行自动拆箱
通过包装类的.equals 或者compareTo方法也同样可以传基本数据类型 (会将基本数据类型装箱,最后通过一些转换进行比较) ,compareTo本质是调用Integer的compare方法拿两个value进行比较大小
为了避免混淆: 如果比较大小时有存在包装类数据 那么最好就包装类对象用其equals方法或者compareTo方法进行比较

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.包装类的缓存机制

了解缓存机制前先来看一段代码…

public static void main(String[] args) {        Integer i=1;        Integer ii=1;        Integer j=128;        Integer jj=128;        Integer k=new Integer(1);        Integer kk=new Integer(1);        System.out.println(i==ii);        System.out.println(j==jj);        System.out.println(k==kk);        //输出结果是什么?    }

按上面分析, 两个包装类对象进行== 比较大小比较的是对象的地址, 此处是四个对象,本应该输出的是三个个false ,但是结果确是 true false false
在这里插入图片描述

为什么会出现上述的情况?
拿Integer包装类为例:
首先,自动装箱会调用Integer.valueOf方法, 通过观察源码发现它并不是直接进行实例化对象
在这里插入图片描述
首先 在valueOf方法里 拿到要装箱的整形 i 进行判断大小 ,如果大于等于low 小于等于high时则会返回IntegerCache的cache数组里的一个对象

private static class IntegerCache {        static final int low = -128;        static final int high;        static final Integer cache[];        static {            // high value may be configured by property            int h = 127;            String integerCacheHighPropValue =                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");            if (integerCacheHighPropValue != null) {                try {                    int i = parseInt(integerCacheHighPropValue);                    i = Math.max(i, 127);                    // Maximum array size is Integer.MAX_VALUE                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);                } catch( NumberFORMatException nfe) {                    // If the property cannot be parsed into an int, ignore it.                }            }            high = h;            cache = new Integer[(high - low) + 1];            int j = low;            for(int k = 0; k < cache.length; k++)                cache[k] = new Integer(j++);            // range [-128, 127] must be interned (JLS7 5.1.7)            assert IntegerCache.high >= 127;        }

在这里插入图片描述

通过观察源码发现, Integer包装类里有一个静态内部类 IntegerCache , 在加载外部类Integer时会加载静态内部类, 此时已经确定low的值为-128 , high在 static修饰的静态代码块里最后获得的值是127

IntegerCache里还有个最重要的cache缓存数组引用 , 它最后会指向一个有256个Integer的引用,
且最后每个Integer都会指向一个Integer对象, 从第一个Integer对象开始存放的是-128 直到第256个对象存放的是value值为127的Integer对象

一句话来讲就是:
在装箱时, 会调用Integer的valueOf方法, 会加载静态内部类IntegerCache , 最后其内部会存在一个缓存数组(里面存放了-128~127 共256个Integer对象) , 当调用valueOf方法时对应的整形数据是在[-128,127] 之间时,会直接使用缓存数组里提前创建好的Integer实例, 如果不在这个范围则会自己实例化一个Integr对象

缓存数组也可以看成是一个对象池,它是一种资源预申请, 在加载时就被创建出来, 当在这个要使用对象时,会在缓存数组里寻找是否已经存在, 如果有则使用缓存数组里的, 没有则自己创建…能够在一定程度上减少创建对象的频率 提高效率 (不是必然的,因为本质上加载会消耗资源,当创建对象的频率较低且value值不在区间里时,这个缓存数组的优势便体现不出来)

注意: 只有调用valueOf方法会出现上述情况, 直接实例化是不会在缓存数组里找的

各种包装类缓存机制:

不存在缓存机制的包装类: Boolean Float Double
Boolean只有True和False两种情况,使用此包装类也不频繁
Float和Double因为都是浮点数在内存中存储会存在精度损失问题,不易创建缓存区

存在缓存机制的包装类:Byte Short Character Integer Long
Byte: -128~127 (正好是byte的范围)
Short: -128~127
Character: 0~127 (char不存在负数)
Integer: -128~127
Long:-128~127
对应的基本数据类型调用valueOf方法进行转换成对应包装类对象时,其数值在这些范围内则会使用加载时生成的缓存数组里的对象, 如果不在范围则自己创建对象

为什么多数缓存区域在-128~127
因为缓存本质上是资源预申请, 它也是创建对象,会消耗资源, 如果缓存区域比较大的情况,那么在加载的时候会更消耗资源,在使用时也不一定频繁用到缓存区域 , 而-128~127这个区间是比较小的预先申请不会占据太多资源,这个区间也是一些常用的数值分布区域,进行一些小数值计算就可以不用频繁的创建对象

三.包装类练习题&面试

写出下面代码输出结果

 public static void main(String[] args) {        Integer i1 = 1;        Integer i2 = 2;        Integer i3 = 3;        Integer i4 = 3;        Integer i5 = 321;        Integer i6 = 321;        Long l1 = 3L;        Long l2 = 2L;        Double d1 = 100.0;        Double d2 = 100.0;        System.out.println(i3==i4);        System.out.println(i5==i6);        System.out.println(d1==d2);        System.out.println(i3==(i1+i2));        System.out.println(l1==(i1+i2));        System.out.println(l1.equals(i1+i2));        System.out.println(l1.equals(i1+l2));        System.out.println(i3.equals(i1+i2));        //输出结果是什么?    }

在这里插入图片描述

涉及到的知识点在上面基本都介绍到:缓存区 里的同一个对象地址是一样的 ,装箱 拆箱 两个包装类用等号比较的是对象地址, 一个包装类一个基本数据则会拆箱比较 , equals则会装箱为包装类进行比较

需要注意的是: 使用equals方法形参是object类型接受 , 接受的基本数据类型会对应装箱为包装类 , 而进行比较时 必须比较的两个包装类类型匹配,如果不匹配哪怕value值相等也是false…

例如第五题: 哪怕Long和Integer里的value值相等,但是 类型不匹配…
在这里插入图片描述

谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

答:
第一种创建方法不会触发自动装箱 ,第二种创建方法会触发自动装箱

在一般情况下,第二种方法比第一种方法执行效率更高,资源占用更低, 因为可能会从缓存数组中拿已经事先创建好的对象使用 … (但是并不是绝对的)

上面知识点也涉及到一些面试知识点, 更多的题后续还会收集补充… 共勉

来源地址:https://blog.csdn.net/lch1552493370/article/details/131872824

--结束END--

本文标题: Java--包装类的学习

本文链接: https://lsjlt.com/news/371497.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java--包装类的学习
    本文介绍了Java中的包装类-- 什么是包装类 ,包装类和基本数据类型之间的关系转换 --装箱与拆箱,包装类的valueOf和XXValue以及构造方法的总结 , 自动装箱和拆箱以及触发的情况 , 包装类内里的缓存机制, 包装类一些相关...
    99+
    2023-08-16
    java 学习 笔记 开发语言
  • 类的封装和包(JAVA)
    目录 封装 在同一个包中: 包 自定义包 在不同包中: 封装 所有的OOP语言都会有三个特征: 封装继承(点击可跳转)多态(点击可跳转) 本篇文章会为大家带来有关封装的知识。 在我们日常生活中可以看到电视就只有那么几个按键(开关...
    99+
    2023-09-01
    java 开发语言
  • 从零开始学习 Java:简单易懂的入门指南之包装类(十九)
    包装类 包装类5.1 概述5.2 Integer类5.3 装箱与拆箱5.4 自动装箱与自动拆箱5.5 基本类型与字符串之间的转换基本类型转换为StringString转换成基本类型 5....
    99+
    2023-08-31
    学习 java 后端 spring cloud spring boot 算法 数据结构
  • Java学习之类的属性(转)
    Java学习之类的属性(转)[@more@] Public、private、protected显示了三种类中的属性和服务的类型,public是可以随意访问的、private是外界不能访问的(显示了数据的封装性)、protected说明数据是...
    99+
    2023-06-03
  • JAVA biginteger类bigdecimal类的使用示例学习
    目录biginteger类的使用BigInteger案例代码bigdecimal类的使用BigDecimal的案例代码biginteger类的使用 A:BigInteger的概述 &...
    99+
    2024-04-02
  • Java--内部类学习笔记
    本文介绍了什么是内部类,Java中的内部类:实例内部类. 静态内部类.局部内部类.匿名内部类的语法和注意事项,以及每个内部类的运用场景,以及简单介绍了匿名内部类更简洁更特殊的语法->lambda表...
    99+
    2023-09-11
    java 学习 笔记
  • Java中的内部类怎么学习
    这篇文章的内容主要围绕Java中的内部类怎么学习进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!看了很多源码,都有用到内部类,但是自己以前在生产环境上...
    99+
    2023-06-16
  • C++11学习之包装器解析
    目录概念类型统一例题:求解逆波兰表达式包装器的意义bind 包装器bind 绑定固定参数调整传参顺序bind包装器的意义概念 function包装器 也叫作适配器。C++中的func...
    99+
    2023-02-13
    C++11包装器解析 C++11包装器 C++ 包装器
  • Java基础之包装类
    目录一、java的包装类二、Integer包装类2.1Integer类的基本介绍2.2Integer类的属性2.3 Integer类的构造器三、自动装箱和自动拆箱四、Int...
    99+
    2024-04-02
  • Java面向对象:抽象类的学习
    本文介绍了抽象类的基本语法概念,什么是抽象类. Java中抽象类的语法,抽象类的特性 抽象类的作用(抽象类和普通类的区别) 用抽象类实现多态… 抽象类的学习 一.什么是抽象类二.抽象类语...
    99+
    2023-09-11
    java 学习 jvm
  • Java Object类和包装类的示例分析
    这篇文章给大家分享的是有关Java Object类和包装类的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。查看源代码方法在IDEA中双击 shift 键,可以搜索相关类名,查看源代码点击Stru...
    99+
    2023-06-29
  • 打包 Java 对象:学习笔记分享
    Java 是一种常用的编程语言,开发者们常常需要将自己编写的 Java 对象打包成可执行的 JAR 文件。本文将分享一些打包 Java 对象的经验和技巧,以便于读者能够更加轻松地完成这项任务。 一、什么是 JAR 文件 JAR 文件是 J...
    99+
    2023-10-04
    打包 对象 学习笔记
  • Java 打包对象:学习笔记分享
    Java 是一门面向对象的编程语言,它的面向对象特性使得 Java 开发者可以轻松地组织代码和数据。但是,在编写代码的过程中,我们经常需要将一组相关的对象打包在一起进行处理。这就是 Java 打包对象的重要作用。本文将会分享 Java 打...
    99+
    2023-10-03
    打包 对象 学习笔记
  • Java学习星球,Java学习路线
    目录 一、Java学习路线二、学习计划三、为何会有Java学习星球?四、加入星球后,你可以得到什么?五、如何加入Java学习星球?六、打卡挑战 大家好,我是哪吒,一个靠着热情攀登至C...
    99+
    2023-08-31
    java 学习 开发语言
  • 怎么理解Java包装类
    这篇文章主要介绍“怎么理解Java包装类”,在日常操作中,相信很多人在怎么理解Java包装类问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Java包装类”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-16
  • Java包装类怎么应用
    这篇文章主要介绍“Java包装类怎么应用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java包装类怎么应用”文章能帮助大家解决问题。一、包装类概述Java有8种基本数据类型:整型(byte、sho...
    99+
    2023-06-29
  • Java包装类的概述与应用
    目录一、包装类概述二、包装类的自动装箱、自动拆箱机制 三、包装类中的缓存机制四、包装类的四则运算、位运算、比较运算、逻辑运算1、四则运算和位运算2、比较运算和逻辑运算五、包...
    99+
    2024-04-02
  • 各类Java高质量学习网址
    Java学习网址: Oracle官方Java学习网站:https://www.oracle.com/java/technologies/javase-downloads.html 2. Java编程思想:https://www.mindv...
    99+
    2023-09-02
    学习
  • Java基础类学习之String详解
    目录1 String不可变性2 不可变的好处3 String+和StringBuilder效率差异4 String, StringBuffer and StringBuilder5 ...
    99+
    2022-12-27
    Java String类 Java String
  • Python学习之装饰器与类的装饰器详解
    目录装饰器装饰器的定义装饰器的用法类中的装饰器类的装饰器 - classmethod类的装饰器 - staticmethod类的装饰器 - property通过学习装饰器可以让我们更...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作