大家好,我是小狼人发JO酸奶,这是我的笔名。作为一个Java程序员,我知道学无止境,顾分享自己的总结笔记,一来希望高人指错,二来希望对大家有帮助。那么我们开始吧!
众所周知,Java有基础数据类型8大、returnAddress(JVM指令指针),以及引用类型,但细节今天个人就写一下自己的积累,希望对你有帮助。
首先8大基础类型有:boolean、byte、short、char、int、long、float、double,这个顺序是逐级的(不用强制转换),对应存储1字节、1字节、2字节、2字节、4字节、8字节、4字节、8字节; 1字节=8bit。32bit最大存储2^32的2进制值,有符号位的=2^32-1
boolean:取值false、true; 默认false ;
byte: 取值-128 ~ 127; 默认0 ;
short: 取值-2^16 ~ 2^16-1; 默认0 ;
char: 取值-2^16 ~ 2^16-1; 默认’’ ; 字符会按照ASCLL值计算大小
int: 取值-2^32 ~ 2^32-1; 默认0;
long: 取值-2^64 ~ 2^64-1; 默认0;
float: 取值-2^32 ~ 2^32-1; 默认0.0;
double: 取值-2^64 ~ 2^64-1; 默认0.0;
汉字占2/3/4字节,但我们经常 char c=’嗨’,其实char只能存Unicode的中文(即2字节的汉字)。
这里要注意long=8字节,float=4字节但可以不用强制转换:1、long的定义长度最大=2^32-1即4字节,所以在字面量赋值时不涉及强转;2、long运行长度=2^64-1(for循环累加可达到),超过2^32-1也可赋给float,这是因为float使用IEEE754标准,float由阶码和尾码组成,此方式可表示出大于long范围的取值,但有精度丢失,顾一般推荐BigDecimal。
以上是8种基础数据类型的介绍,下面看看他们的包装类,以对象的形式存在:
Boolean、Byte、Short、Character、Integer、Long val=1l、Float val=1f、Double val=1d
在赋值时要考虑到JVM常量池(后期讲),数值在-128 到 127间不创建新对象,如下例:
Integer i=100; Integer n=100; i==n true, 数值-128 到 127间,常量池已存在不新建对象
Integer i=100; Integer n=new Integer(100); i==n false 强制新建包装类对象
Integer i=200;Integer n=200、 i==n false 包装类对象,不在数值-128 到 127间
Integer i=new Integer(200); int n=200; i==n true, 和基础类型比较,统一为值比较
Byte、Short、Character、Integer 值为-128~127时,相同类型使用==比较,结果均为true。
Float i1=127f,i2=127f;Long i1=127l,i2=127l;Double i1=127d,i2=127d;两两相比均为false。
注意:不同类型的包装对象不能用 == 进行比较。
再来说说引用类型:数组、类、接口;字符串String就是final修饰的不可变char数组:
String: 底层private final char value[]; 定义长度=2^16-1、运行长度=2^32-1,
String不可变:1.避免多对象引用时有安全问题;2.(保证hash码唯一)可缓存HashCode提高效率。
String删除方法:trim/replace是删ASCLL值32以下字符;strip是删Unicode中的空白符(更多)。
注意:一般对象进行equals方法比较,底层还是==,项目中要自己重写,但String已重写。
JDK9中String 底层改为 byte[] 数组、UTF-8 改为 UTF-16,原因概括如下:
1.改为byte数组节省内存空间,降低垃圾回收,有些字符仅1个字节即可表示,byte有2种编码分别用于处理单字节和多字节。
2.charAt、subString等某些方法是随机访问的,因为UTF-8以字符存储,占用空间不固定,需遍历寻找;UTF-16以2或4字节存储,视为占用空间固定,直接计算定位查找。
相对于常量池,字符串也有字符串常量池来避免过多的创建:
JVM字符串常量池避免频繁创建,若字符串常量池中已有,则新变量=原字符串的地址值;
String s1=”OA”, s2=”O”+”A”, s3=”O”+’A’, s4=””+’O’+’A’ 。则有s1==s2==s3==s4==true;
String s5=’O’+’A’+”” s1==s5 false, 因为先计算’O’+’A’会变成ASCLL值的计算;
String s6=new String(”OA”) s1==s6 false, 强行在堆上创建空间,新的字符串;
String s7=String.ValueOf(90) s1==s7 false,因为String.ValueOf() 底层是new String();
注意:Java1.8版,方法区移除永久代改为元空间,各种常量池均由堆划分,不再是方法区。
对象在这里我聊一下不常提的知识吧:对象创建流程、对象结构;
对象创建过程:
- JVM判断新建对象指令参数是否能在常量池中定义到一个类的符号引用再加载类。
- 内存分配方式:指针碰撞、空闲列表、本地线程缓冲区(默认方式)。
- 初始化(static)变量。
- 处理对象头。
对象结构:
- 对象头:包含MarkWorld、对象类型指针、如果是数组(要有数组长度); MarkWorld是4部分的组成:HashCode值、分代年龄、锁标志、是否为偏向锁的标志。
- 实体数据:对象的变量和方法等数据。
- 对齐填充:当对象不足8字节时会填充至8字节,即使是空对象也会是8字节。
声明:因文章是个人笔记,顾偏向于知识总结,文中提到的相关知识还需细化学习,因篇幅有限无法逐一讲解,最后谢谢支持与指正。