@@ -592,9 +592,9 @@ public class Test1 {
592592
593593 运算符:
594594
595- * `>>`运算符:将二进制位进行右移操作,相当于除 2
596- * `<<`运算符:将二进制位进行左移操作,相当于乘 2
597- * `>>>`运算符:无符号右移,忽略符号位,空位都以0补齐
595+ * `>>` 运算符:将二进制位进行右移操作,相当于除 2
596+ * `<<` 运算符:将二进制位进行左移操作,相当于乘 2
597+ * `>>>` 运算符:无符号右移,忽略符号位,空位都以0补齐
598598
599599 运算规则:
600600
@@ -4713,7 +4713,7 @@ HashMap继承关系如下图所示:
47134713 static final int TREEIFY_THRESHOLD = 8;
47144714 ```
47154715
4716- 为什么 Map 桶中节点个数大于8才转为红黑树 ?
4716+ 为什么 Map 桶中节点个数大于 8 才转为红黑树 ?
47174717
47184718 * 在 HashMap 中有一段注释说明:**空间和时间的权衡**
47194719
@@ -4936,22 +4936,22 @@ HashMap继承关系如下图所示:
49364936
49374937 存储数据步骤(存储过程):
49384938
4939- 1. 先通过hash值计算出key映射到哪个桶
4939+ 1. 先通过 hash 值计算出 key 映射到哪个桶
49404940
49414941 2. 如果桶上没有碰撞冲突,则直接插入
49424942
49434943 3. 如果出现碰撞冲突:如果该桶使用红黑树处理冲突,则调用红黑树的方法插入数据;否则采用传统的链式方法插入,如果链的长度达到临界值,则把链转变为红黑树
49444944
4945- 4. 如果数组位置相同,通过equals比较内容是否相同:相同则新的value覆盖之前的value ,不相同则将新的键值对添加到哈希表中
4946- 5. 如果size大于阈值threshold ,则进行扩容
4945+ 4. 如果数组位置相同,通过 equals 比较内容是否相同:相同则新的 value 覆盖旧 value ,不相同则将新的键值对添加到哈希表中
4946+ 5. 如果 size 大于阈值 threshold ,则进行扩容
49474947
49484948 ```java
49494949 public V put(K key, V value) {
49504950 return putVal(hash(key), key, value, false, true);
49514951 }
49524952 ```
49534953
4954- putVal()方法中key在这里执行了一下hash (),在putVal函数中使用到了上述hash函数计算的哈希值 :
4954+ putVal() 方法中 key 在这里执行了一下 hash (),在 putVal 函数中使用到了上述 hash 函数计算的哈希值 :
49554955
49564956 ```java
49574957 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
@@ -11300,7 +11300,7 @@ public Object pop() {
1130011300 unused(25+1) + hash(31) + age(4) + lock(3) = 64bit #64位系统
1130111301 ```
1130211302
11303- * **Klass Word**:类型指针,指向该对象的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;在64位系统中,开启指针压缩(-XX:+UseCompressedOops)或者 JVM 堆的最大值小于 32G,这个指针也是 4byte,否则是 8byte(就是 Java 中的一个引用的大小)
11303+ * **Klass Word**:类型指针,指向该对象的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;在64位系统中,开启指针压缩(-XX:+UseCompressedOops)或者 JVM 堆的最大值小于 32G,这个指针也是 4byte,否则是 8byte(就是 ** Java 中的一个引用的大小** )
1130411304
1130511305 ```ruby
1130611306 |-----------------------------------------------------|
@@ -11310,7 +11310,7 @@ public Object pop() {
1131011310 |---------------------------|-------------------------|
1131111311 ```
1131211312
11313- * 数组对象:如果对象是一个数组,那在对象头中还有一块数据用于记录数组长度
11313+ * 数组对象:如果对象是一个数组,那在对象头中还有一块数据用于记录数组长度(12 字节)
1131411314
1131511315 ```ruby
1131611316 |-------------------------------------------------------------------------------|
@@ -11352,7 +11352,7 @@ public Object pop() {
1135211352
1135311353#### 实际大小
1135411354
11355- 浅堆(Shallow Heap):**对象本身占用的内存,不包括内部引用对象的大小**,32 位系统中一个**对象引用占 4 个字节** ,每个对象头占用 8 个字节,根据堆快照格式不同,对象的大小会同 8 字节进行对齐
11355+ 浅堆(Shallow Heap):**对象本身占用的内存,不包括内部引用对象的大小**,32 位系统中一个对象引用占 4 个字节,每个对象头占用 8 个字节,根据堆快照格式不同,对象的大小会同 8 字节进行对齐
1135611356
1135711357JDK7 中的 String:2个 int 值共占 8 字节,value 对象引用占用 4 字节,对象头 8 字节,对齐后占 24 字节,为 String 对象的浅堆大小,与 value 实际取值无关,无论字符串长度如何,浅堆大小始终是 24 字节
1135811358
@@ -11396,7 +11396,7 @@ private int hash32;
1139611396
1139711397#### 节约内存
1139811398
11399- * 尽量使用基本类型
11399+ * 尽量使用基本数据类型
1140011400
1140111401* 满足容量前提下,尽量用小字段
1140211402
@@ -11409,7 +11409,7 @@ private int hash32;
1140911409 private int size;
1141011410 ```
1141111411
11412- Mark Word 占 4byte,Klass Word 占 4byte,一个 int 字段占 4byte,elementData 数组占 12(4+4+4) ,数组中 10 个 Integer 对象占 10×16,所以整个集合空间大小为 184byte(深堆)
11412+ Mark Word 占 4byte,Klass Word 占 4byte,一个 int 字段占 4byte,elementData 数组占 12byte ,数组中 10 个 Integer 对象占 10×16,所以整个集合空间大小为 184byte(深堆)
1141311413
1141411414* 时间用 long/int 表示,不用 Date 或者 String
1141511415
@@ -11421,15 +11421,15 @@ private int hash32;
1142111421
1142211422#### 对象访问
1142311423
11424- JVM 是通过栈帧中的对象引用访问到其内部的对象实例 :
11424+ JVM 是通过**栈帧中的对象引用**访问到其内部的对象实例 :
1142511425
1142611426* 句柄访问:Java 堆中会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息
1142711427
1142811428 优点:reference 中存储的是稳定的句柄地址,在对象被移动(垃圾收集)时只会改变句柄中的实例数据指针,而 reference 本身不需要被修改。
1142911429
1143011430 <img src="https://gitee.com/seazean/images/raw/master/Java/JVM-对象访问-句柄访问.png" style="zoom: 50%;" />
1143111431
11432- * 直接指针(HotSpot采用 ):Java 堆对象的布局必须考虑如何放置访问类型数据的相关信息,reference 中直接存储的对象地址
11432+ * 直接指针(HotSpot 采用 ):Java 堆对象的布局必须考虑如何放置访问类型数据的相关信息,reference 中直接存储的对象地址
1143311433
1143411434 优点:速度更快,**节省了一次指针定位的时间开销**
1143511435
@@ -11475,9 +11475,9 @@ Java 对象创建时机:
1147511475
11476114761. 使用 new 关键字创建对象:由执行类实例创建表达式而引起的对象创建
1147711477
11478- 2. 使用 Class 类的 newInstance 方法 ( 反射机制)
11478+ 2. 使用 Class 类的 newInstance 方法( 反射机制)
1147911479
11480- 3. 使用 Constructor 类的 newInstance 方法( 反射机制)
11480+ 3. 使用 Constructor 类的 newInstance 方法( 反射机制)
1148111481
1148211482 ```java
1148311483 public class Student {
@@ -12920,7 +12920,7 @@ double j = i / 0.0;
1292012920System.out.println(j);//无穷大,NaN: not a number
1292112921```
1292212922
12923- 分析 i++:从字节码角度分析:a++ 和 ++a 的区别是先执行 iload 还是 先执行 iinc
12923+ ** 分析 i++** :从字节码角度分析:a++ 和 ++a 的区别是先执行 iload 还是 先执行 iinc
1292412924
1292512925```java
1292612926 4 iload_1 //存入操作数栈
@@ -13960,15 +13960,15 @@ public class Candy4 {
1396013960}
1396113961```
1396213962
13963- 可变参数`String... args`其实是`String[] args` , java 编译器会在编译期间将上述代码变换为:
13963+ 可变参数 `String... args` 其实是 `String[] args` , java 编译器会在编译期间将上述代码变换为:
1396413964
1396513965```java
1396613966public static void main(String[] args) {
1396713967 foo(new String[]{"hello", "world"});
1396813968}
1396913969```
1397013970
13971- 注意:如果调用了foo() 则等价代码为`foo(new String[]{})` ,创建了一个空的数组,而不会传递 null 进去
13971+ 注意:如果调用了 foo() 则等价代码为 `foo(new String[]{})` ,创建了一个空的数组,而不会传递 null 进去
1397213972
1397313973
1397413974
@@ -17392,7 +17392,7 @@ UML 从目标系统的不同角度出发,定义了用例图、类图、对象
1739217392
1739317393* 双端检锁机制
1739417394
17395- 在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作 ,所以需要使用 `volatile` 关键字
17395+ 在多线程的情况下,可能会出现空指针问题,出现问题的原因是 JVM 在实例化对象的时候会进行优化和指令重排序操作 ,所以需要使用 `volatile` 关键字
1739617396
1739717397 ```java
1739817398 public class Singleton {
0 commit comments