数组及其内存管理
- java数组是静态的(静态变量被初始化之后不可以再次赋值),当数组被初始化之后该内存空间和数组长度都不可以变化。
- 静态数组初始化 (指定数组内容,由系统指定数组长度)
- 动态初始化(指定数组长度之后再次赋值数组内容)
- java数组变量是一种引用变量,数组变量并不是数组本身,他是指向堆内存中的数组对象
- 对数组执行初始化,并不是对数组变量执行初始化,而是对数组对象初始化,分配一块连续的内存空间。
- 所有的局部变量都是存储在栈内存中保存的,不管是基本类型的变量还是引用类型的变量,都是存储在各自的方法栈中;但引用类型的变量所引用的对象(包括数组和java对象)则总是存储在堆内存中。
- 区分引用变量与java对象:引用对象的本质上只是一个指针,只有程序通过引用变量访问属性、方法该引用变量就会由他锁引用的对象代替。
对象及其内存管理
- 实例变量初始化时机
- 定义实例变量时指定初始化值
- 非静态代码块中对实例变量指定初始化值
- 构造器中指定初始化值
** 前两种由定义语句的顺序初始化,第3种最后执行 **
- 定义实例变量时,指定初始值、初始化块中为实例变量指定初始值的语句的地位是平等的,经过编译器处理后被提取到构造器中。
- 类变量初始化时机
- 定义类变量时指定初始化时机
- 静态初始化块中对类变量指定初试值
这两种方式执行顺序与他们在源程序中排列顺序相同
- 父类构造器:程序总会依次调用每个父类的非静态初始化块,构造器执行初始化,然后才调用本类的非静态代码块和构造器执行初始化。
- 构造器的初始化
- 子类构造器显示super调用父类构造器
- 子类构造器显示调用this重载构造器
- 子类构造器既没有super也没有this则隐式调用父类无参构造器
- this()和super()有且只能在构造器中被调用一次
- final 修饰符的一个重要作用就是定义宏变量,当定义final变量时就为该变量指定了初始值,而且该初始值可以再编译时就确定下来;编译器会在程序中所有用到该变量的地方直接替换成该变量的值。
- 只有在定义dinal类变量时指定初始值,系统才会对final变量执行宏替换。
- 隐式闭包 疯狂java讲义 6.7
常见JAVA集合实现的细节
- ArrayList 默认封装的数组长度为10
- hashmap的容量resize 是以2倍来扩充;扩充的条件是 size++>hashMap容量*负载因子
- hashSet基于hashMap实现
- treeSet实现了NavigableMap接口,底层仍然采用treeMap实现。
- treeMap中总是按照指定的key来进行排序;但是treeSet中所有元素根据指定规则排序。
- arrayList如果添加元素超过了底层数组长度,arrayList必须创建一个长度为原来1.5倍的数组;再由垃圾回收机制回收原有的数组,因此系统开销较大
JAVA内存回收
-
对象在JVM中的状态
- 可达状态(创建之后)
- 可恢复状态(可达状态失去引用之后变为可恢复状态,jvm调用该对象的finalize方法对资源进行回收,如果该对象重新变得可被引用则变为可达状态,否则进入不可达状态)
- 不可达状态(彻底失去引用)
- 垃圾回收
-
JAVA对象的引用有4种
- 强引用(创建一个对象赋值给引用变量)
- 弱引用(通过实现WeakReference实现,比软引用级别更低,当垃圾回收机制运行时,该对象被回收,不管系统空间是否充足)
- 软引用(通过softReference类实现,当系统空间不足时,系统将会回收)
- 虚引用
-
常见的垃圾回收器
- 串行回收器
- young采用串行复制算法
- old采用串行标记清除算法
- 并行回收器
- young采用类似于串行复制算法,但是多个线程执行回收;线程数量为CPU数量
- old依旧采用串行标记整理的算法
- 并行压缩回收器
- young采用与并行回收器策略相同
- 并发标识-清理回收器(CMS)
- young采用与并行回收器策略相同
- CMS对old的回收多数是并发操作而不是并行操作
- 串行回收器
java 工具介绍
- javap 帮助开发者深入了解编译器的机制