1、基本数据类型
bit 对应一个数值 , 也就是一个2, 8个bit = 1字节
基本数据类型存放在java的栈的局部变量区内,而java的栈是跟着方法去创建的。
1.1、byte
byte指的是整数型数值,范围是-127 到 127. 也就是 -2^8 到 2^8,占用内存一个字节
1.2、short
short指的是整数型数值,范围是 -2^16 到 2^16。 占用内存两个字节
1.3、int
int指的是整数型数值,范围是 -2^32 到 2^32。占用内存4个字节
1.4、long
long指的是整数型数值,范围是 -2^64 到 2^64。占用内存8个字节
1.5、float
float指的是浮点型数值,单精度,范围是 -2^32 到 2^32。
单精度:
1、在内存中占4个字节,
2、有效数字位数8位,
3、只有一位小数位,不能用于高精度运算中,因为乘法除法都可能产生比原数据多的小数位,但是如果使用单精度的float接收就会造成小数位丢失,这就会造成整体数据结果的不严谨,这种对于金额计算来说是不允许的
1.6、double
double指的是浮点型数值,双精度,范围是 -2^64 到 2^64。
双精度:
1、在内存中占8个字节,
2、有效数字位数16位,
3、只有两位小数位,不能用于高精度运算中,因为乘法除法都可能产生比原数据多的小数位,但是如果使用单精度的float接收就会造成小数位丢失,这就会造成整体数据结果的不严谨,这种对于金额计算来说是不允许的
1.7、boolean
对于boolean 来说 它标识真或假,对于计算机来说完全可以用 0或者1来表达,这意味着他只需要占用一个bit 的内存空间,但是对于现代计算机而言,8位bit也就是一个字节才是计算运行的基本单位,因此计算机会给内存内补上0来使得boolean占有一个字节。
而对于java而言,jvm虚拟机基于计算机对于32位也就是4个字节的处理速度更快,因此虚拟机会使用int类型来处理,这样子呢就是占用了4个字节
当然,如果是boolean数组,jvm又会使用byte数组来接收,这样算来单个值又只是一个字节了
1.8、char
由于java使用Unicode编码,而Unicode编码需要两个字节才可以展示所有,所以java中char占两个字节,这里需要注意的是中文根据不同的编码会对应不同的字节,2-4都是有可能的。
2、基于基本数据类型的装箱类型
装箱后会生成一个对象,因此这些都会存放在堆中。
为什么会诞生装箱类?
对于基本数据类型来说,他不是一个类,也不能继承自object,因此也不能使用方法,但是在一些情况下我们需要对象来进行处理,比如:泛型。
装箱之后带来的问题。
装箱类由于是对象,如果用==来做比较呢,对于基本类型的装箱类和String来说是进行了比较对象在内存地址的,因此 new Integer(100) 和new Integer(100)是不等的。
另一个问题是,由于存在常量缓存也就是常量池,而缓存范围为-127 -》127 那么 integer a = 100;和 integer b = 100;是相等的,但是integer a = 200;和 integer b = 200;却是不相等的,
每一个基础类型都有对应的装箱对象,分别是 Byte,Short,Integer,Long,Float,Double,Boolean,Char
3、使用最多的不可变对象String
什么是String?
String类是用于编辑字符串的一个不可变的对象。拥有一系列对字符串进行操作的方法。
String的实现方式?
java底层用一个不可变的char[]来储存字符串。
为什么说String是不可变?这个不可变到底是什么不可变?怎么实现的?
上面说到String类是一个对象,那么他在java的内存中就存在堆中,而方法在调用时,基本操作都在栈中,因此对于对象来说都有一个指针,指向对象所在堆中的位置。这里所指的不可变其实就是对象所在堆的位置是不会变的。如果对String进行操作,那么会在堆中新建一个新的内存地址来存储新的字符串,原来的String还在原来的地方没有变化,这就是String的不可变。
实现的话,很简单,使用final关键词进行修饰即可。
为什么要将String设计为不可变呢?
1、由于String的底层是char数组,而如果String的值可以变的话,意味着char数组需要扩容才能放下,而如果缩短字符串长度又会造成char数组不饱和,浪费了空间,也就是扩充字符串会浪费性能,而缩短字符串就会造成空间的浪费。
2、安全问题,由于String是大多数方法的参数,如果可以改变的话,很可能被人篡改造成数据问题。
3、多线程的安全问题,多线程并发时,不同线程修改同一个String,就会出现线程问题,如果是不可变就不存在这个问题了。
java怎么优化String的呢?
1、由于大量使用String,java也就是用了类似缓存的方式来进行优化,诞生了字符串常量池,在这个池子中如果有String已经创建过,那么新的字符串如果和原有的一致那么就直接把引用给新的对象即可,无需频繁的生成对象和销毁对象了。
2、之前的博客有说过面向对象编程比面向过程编程的性能差,一个很重要的原因就是因为有大量的对象的创建和销毁。所以就有了StringBuilder的诞生,StringBuilder是可变的,对其操作不会产生新的对象也就不存在对象销毁和创建问题,提高了性能,但是上面有说过,如果是可变的话会带来一个多线程情况下的线程安全问题,因此又出现了一个新的类,StringBuffer,这个是线程安全的类,体现在他的每一个方法都是同步方法也就是被锁所修饰了的,但是这样他的性能也就比StringBuilder差一些,根据这个其实也就可以知道我们应该怎么使用这两个类了。
本文详细介绍了Java中的基本数据类型,包括byte、short、int、long、float、double、boolean和char的范围及内存占用。同时讨论了基于基本数据类型的装箱类型,如Integer、Character等,以及装箱带来的问题。最后,文章深入讲解了不可变对象String的原理、实现及为何设计为不可变,并探讨了Java如何通过字符串常量池和StringBuilder/StringBuffer来优化性能。

被折叠的 条评论
为什么被折叠?



