4.垃圾回收机制
内存管理
Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。
对象空间的分配:使用new关键字创建对象即可
对象空间的释放:将对象赋值null即可。垃圾回收器将负责回收所有”不可达”对象的内存空间
·垃圾回收过程
1) 发现无用的对象
2) 回收无用对象占用的内存空间。
垃圾回收机制保证可以将“无用的对象”进行回收。无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。
·垃圾回收相关算法
1) 引用计数法
堆中每个对象都有一个引用计数。被引用一次,计数加1. 被引用变量值变为null,则计数减1,直到计数为0,则表示变成无用对象。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。
2) 引用可达法(根搜索算法)
程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。
通用的分代垃圾回收机制
1)思想
不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。
说明:我们将对象分为三种状态:年轻代、年老代、持久代。
JVM将堆内存划分为 Eden、Survivor 和 Tenured/Old 空间。
2)年轻代、年老代、持久代
1. 年轻代
所有新生成的对象首先都是放在Eden区。 年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC,每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法,频繁的操作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域。
2. 年老代
在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代对象越来越多,我们就需要启动Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域。
3. 持久代
用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响。
说明:·Minor GC:用于清理年轻代区域。Eden区满了就会触发一次Minor GC。清理无用对象,将有用对象复制到“Survivor1”、“Survivor2”区中
Major GC:用于清理老年代区域
Full GC:用于清理年轻代、年老代区域。 成本较高,会对系统性能产生影响。
3)垃圾回收过程
1、新创建的对象,绝大多数都会存储在Eden中,
2、当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区
3、当Eden区再次满了,会将S1中的不能清空的对象存到另外一个Survivor中,如S2,同时将Eden区中的不能清空的对象,也复制到S1中,保证Eden和S1,均被清空。
4、重复多次(默认15次)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)区中,
5、当Old区满了,则会触发一个一次完整地垃圾回收(FullGC),之前新生代的垃圾回收称为(minorGC)
5.this关键字
对象创建的过程
1. 分配对象空间,并将对象成员变量初始化为0或空
2. 执行属性值的显示初始化
3. 执行构造方法
4. 返回对象的地址给相关的变量
this的本质
this的本质就是“创建好的对象的地址” 由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象” 。对当前对象的引用,当前对象的引用地址
this的用法
使用this关键字区分成员变量和局部变量
使用this关键字访问当前的属性和方法,this可以省略
使用this关键字调用构造方法,必须处在构造方法的第一行
注意:this关键字不能和static关键字结合使用
6.static关键字
Static修饰变量称为静态成员变量,也称为类变量( 类变量的生命周期和类相同,在整个应用程序执行期间都有效),static修饰方法称为静态方法
核心要点
static修饰的成员变量和方法,从属于类
普通变量和方法从属于对象
使用的时间
在类加载时,(创建对象之前),对该变量进行初始化。所有对象共享一份静态成员变量
用法
1)可以使用static修饰成员变量(类变量,从属于类)
类变量访问方式:
a.对象名.属性名 b.类名.属性名
成员变量访问方式
对象名.属性名
2)可以使用static修饰方法(静态方法,从属于类)
访问方式
a.对象名.方法名 b. 类名.方法名
3)可以使用static修饰代码块(静态代码块,在类加载时执行,创建对象之前)
static{
静态代码块
}
4)使用static修饰内部类(静态内部类)
注意:非静态的方法时可以访问静态的成员变量
静态方法不能访问非静态的成员变量
静态初始化块
1)作用
构造方法用于对象的初始化,静态初始化块,用于类的初始化操作。
注意:静态初始化块执行顺序
1. 上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。
2. 构造方法执行顺序和上面顺序一样
编写代码及运行结果
7.参数传递机制
值传递
传递的是值的副本。副本改变不会影响原件
参数为基本数据类型,都属于值传递
引用传递
引用传递传递的是对象的地址引用,会保留更改的结果
参数为引用类型的数据(Person,类)(类,接口,数组)都属于引用传递
8.包
作用
包的作用类似于文件夹 :1.分类管理 2.避免命名冲突
声明包
package 包名;(声明包必须放在类上面的第一行非注释语句)
eg:package com.sxt.oop;
包的命名规范:
1.所有包名都应该小写
2.包名应该遵循域名反写+功能包名称
eg:com.sxt.oop com.oracle.net
几种常用的包
JDK中常用的包除了java.lang下的类或接口可以不用导包直接使用外,其他包下的类或接口必须导包后才能使用
如何导包
快捷键ctrl+shift+o
1.import 包名.类名;
2.import 包名.*;
在eclipse项目中新建包
9.导入类import
如果我们要使用其他包的类,需要使用import导入,从而可以在本类中直接通过类名来调用,否则就需要书写类的完整包名和类名。
导入方式
1.import 包名.类名;(导入某一类的包)
2.import 包名.*;(导入所有类的包)
注意要点:1. Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
2. 如果导入两个同名的类,只能用包名+类名来显示调用相关类
静态导入
静态导入(static import)是在JDK1.5新增加的功能,其作用是用于导入指定类的静态属性,这样我们可以直接使用静态属性。
10.继承
定义
继承代表了一种“is-a”关系,如果A是B,则可以说A继承了B
一般父类更加通用(保存通用的代码),子类更加具体(子类:拥有父类声明的非私有的属性和方法)
格式
java中使用extends关键字,建立继承关系,在java中继承是单继承(一个子类只能继承一个父类),c++可以是多继承
public class 子类 extends 父类{
}
使用要点
1.父类也称作超类、基类、派生类等。
2.Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
3.Java中类没有多继承,接口有多继承。
4.子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
5.如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
instanceof运算符
1)instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true,否则,返回false
2)用途
主要用途:用于防止类型转换异常