2019-07-16

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)用途

主要用途:用于防止类型转换异常


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容