版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1. 对象内存管理1.1. 对象内存管理1.1.1. 对象内存管理在JAVA中,有java程序、虚拟机、操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统交互。编译好的java字节码文件运行在JVM中。程序中无论代码还是数据,都需要存储在内存中,而java程序所需内存均由JVM进行管理分配,开发者只需关心JVM是如何管理内存的,而无需关注某种操作系统是如何管理内存的,这就保证了java程序的平台无关性。JVM会将申请的内存从逻辑上划分为三个区域:堆、栈、方法区。这三个区域分别用于存储不同的数据。1.2. 堆内存1.2.1. 对象存储在堆中JVM在其内存空间开辟了一个称为“堆”的
2、存储空间,这部分空间用于存储使用new关键字所创建的对象。请看如下代码:1. Cell c = new Cell ();其内存分布如图 1所示:图- 1从图示1中可以看到右侧的堆内存,new Cell()所创建的对象在堆中分配,同时成员变量亦在此分配,并赋初始值为零。引用类型变量c在栈内存中分配,其中保存的数据,为对象在堆内存中的地址信息,假设对象在堆内存的地址为40DF,则c中保存的即是40DF。1.2.2. 成员变量的生命周期当声明好对象之后,对该对象(堆中的Cell)的访问需要依靠引用变量(栈中的c),那么当一个对象没有任何引用时,该对象被视为废弃的对象,属于被回收的范围,同时该对象中的
3、所有成员变量也随之被回收。可以这样认为,成员变量的生命周期为:从对象在堆中创建开始到对象从堆中被回收结束。请看如下的代码,演示了对象不再被引用:1. Cell c = new Cell();2. c = null ;当将c赋值为null时,表示c不再指向刚刚分配的对象空间,此时成员变量失效。1.2.3. 垃圾回收机制垃圾回收器(Garbage Collection,GC)是JVM自带的一个线程(自动运行着的程序),用于回收没有任何引用所指向的对象。GC线程会从栈中的引用变量开始跟踪,从而判定哪些内存是正在使用的,若GC无法跟踪到某一块堆内存,那么GC就认为这块内存不再使用了,即为可回收的。但是
4、,java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。1.2.4. Java程序的内存泄露问题内存泄露是指,不再被使用的内存没有被及时的回收,严重的内存泄露会因过多的内存占用而导致程序的崩溃。在程序中应该尽量避免不必要的内存浪费。GC线程判断对象是否可以被回收的依据是该对象是否有引用来指向,因此,当确定该对象不再使用时,应该及时的将其引用设置为null,这样,该对象即不再被引用,属于可回收的范围。1.2.5. System.gc()方法GC的回收对程序员来说是透明的,并不一定一发现有无引用的对象就立即回收。一般情况下,当我们需要GC线程即刻回收无用对象时,可以调用System.gc(
5、)方法。此方法用于建议JVM马上调度GC线程回收资源,但具体的实现策略取决于不同的JVM系统。1.3. 非堆-栈1.3.1. 栈用于存放方法中的局部变量JVM在其内存空间开辟一个称为”栈”的存储空间,这部分空间用于存储程序运行时在方法中声明的所有的局部变量,例如,在main方法中有如下代码:1. Cell c = new Cell ( );2. int num = 5;其内存分配如图 2 所示:图- 2说明:方法中的变量即为局部变量,是在栈内存中分配,若变量为值类型,则在栈中存储的就是该变量的值。若变量为引用类型,则在栈中存储的是堆中对象的地址。1.3.2. 局部变量的生命周期一个运行的Jav
6、a程序从开始到结束会有多次方法的调用。JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为该方法的栈帧。一个栈帧对应一个正在调用中的方法,栈帧中存储了该方法的参数、局部变量等数据。当某一个方法调用完成后,其对应的栈帧将被清除,局部变量即失效。1.3.3. 成员变量和局部变量成员变量与局部变量的差别如下:局部变量:1) 定义在方法中;2) 没有默认值,必须自行设定初始值;3) 方法被调用时,存在栈中,方法调用结束时局部变量从栈中清除;成员变量:1) 定义在类中,方法外;2) 由系统设定默认初始值,可以不显式初始化;3) 所在类被实例化后,存在堆中,对象被回收时,成员变量失效;1.4.
7、 非堆-方法区1.4.1. 方法区用于存放类的信息方法区用于存放类的信息,Java程序运行时,首先会通过类装载器载入类文件的字节码信息,经过解析后将其装入方法区。类的各种信息(包括方法)都在方法区存储,看如下代码:1. Cell c = new Cell();程序在执行这句话时,Cell类首先被装载到JVM的方法区,其中包括类的基本信息和方法定义等,如下图 3 所示:图- 3通过图示可以看出,在方法区中,包含Cell类的字节码文件,及类的基本信息及方法drop等。1.4.2. 方法只有一份当类的信息被加载到方法区时,除了类的类型信息以外,同时类内的方法定义也被加载到方法区;类在实例化对象时,多
8、个对象会拥有各自在堆中的空间,但所有实例对象是共用在方法区中的一份方法定义的。意味着,方法只有一份。看如下代码:1. JFrame f1 = new JFrame(); 2. JFrame f2 = new JFrame(); 3. f1.setSize(200, 300);4. f2.setSize(300,400); 如上的代码中,对象有两个,但是setSize方法只有一份,分别针对f1指向的对象和f2指向的对象调用了两次。2. 继承的意义(上)2.1. 继承2.1.1. 泛化的过程前面的案例中定义了T类和J类, 通过分析可以发现, 在这两个类中存在着大量的重复代码,像cells属性、pr
9、int方法、drop方法、moveLeft方法、moveRight方法,在这两个类中都存在,并且实现上基本也是相同的,本着代码重用的原则,可以使用继承的方式来实现。首先,构建T类和J类的父类Tetromino类,将公共的(T类和J类公有的)信息存放在父类中, T类和J类继承Tetromino父类。此时,子类即可以共享父类的数据。这个过程就是泛化的过程。2.1.2. extends关键字使用继承可以实现代码的重用,在java语言中,需要通过extends关键字实现类的继承。继承完成后,子类(Sub class)可以继承父类(Super class)的成员变量及成员方法,同时子类也可以定义自己的成
10、员变量和成员方法。届时,子类将具有父类的成员及本类的成员。需要注意的是,Java语言不支持多重继承,即:一个类只能继承一个父类,但一个父类可以有多个子类。看下面的代码:1. public class Tetromino 2. Cell cells;3. public Tetromino() 4. cells = new Cell4;5. 6. &
11、#160; public void drop() /同写过的T类 7. public void moveLeft() /同写过的T类8. public void moveRight() /同写过的T类9. public void print() /同写过的T类10. 11. public class TetrominoT extends Tetromino 12. public Te
12、trominoT(int row, int col) 13. cells0 = new Cell(row, col);14. cells1 = new Cell(row, col + 1);15. cells2 = new Cell(row, col + 2);16.
13、60; cells3 = new Cell(row + 1, col + 1); 17. 18. 如上代码说明:声明父类Tetromino,将公共信息放在其中,包括Cell声明、drop()方法、moveLeft()方法、moveRight()方法,print()方法。声明无参构造函数,对成员变量Cell数组进行实例化。声明子类TetrominoT继承Tetromino,并声明有参构造函数,传递行row,列col参数,进行T型数组元素的初始化。下面在main方法中,声明一个T型对象,即可以实现T型对象
14、的构建:1. TetrominoT t = new TetrominoT( 1 , 1);上面的代码,在创建子类对象时,调用了子类的有参构造函数进行数据的初始化,试想下,父类Tetromino的无参构造函数执行了吗?通过分析可以肯定的是,父类的无参构造函数被执行了。在程序中并没有声明父类的构造函数,那它是如何执行的呢?2.1.3. 继承中构造方法父类的无参构造方法之所以被执行,是因为java规定,子类在构造之前必须先构造父类。事实上,子类的构造方法中是必须要通过super关键字来调用父类的构造方法的,这样才可以保证妥善的初始化继承自父类的成员变量。但是看上一个案例中的代码并没有super调用父
15、类构造方法,那是因为,如果子类的构造方法中没有调用父类的构造方法,则java编译器会自动的加入对父类无参构造方法的调用。请看如下代码,演示了super关键字的用法:1. public TetrominoT(int row, int col) 2. super ( ) ; 3. cells0 = new Cell(row, col);4. cells1 = new Cell(row, col + 1);5.
16、;6. 上面的代码中,super();为编译器自动加入的,并且super关键字必须位于子类构造方法的第一行,否则会有编译错误。另外一点需要注意的是,若父类没有提供无参的构造方法,则会出现编译错误。请看如下的示例:1. class Foo /父类2. int value;3. Foo(int value) 4. this.value = value;5. 6. 7. class Goo extends Foo /子类8. int num;9. Goo(int num) 10. this.num = num;11. 12. 分析上面的代码,在子类构造方法中没有写super调用父类构造方法,这时编译
17、器会默认添加super()来调用父类的无参构造方法,但是父类中又没有定义无参的构造方法,因此会发生编译错误。针对上面的问题,可以有两种解决方案,方案一为在父类中添加无参的构造方法,方案二为在子类构造方法中显示调用父类的有参构造方法(常常使用),这样可以保证父类的成员变量均被初始化,参见下面的代码:1. class Goo extends Foo 2. int num;3. Goo(int value, int num) 4. super(value);5. this.num = num6. 7. 如上的代码,在子类中调用了父类的构造方法,初始化了继承自父类的value成员变量,编译正确。2.1
18、.4. 父类的引用指向子类的对象一个子类的对象可以向上造型为父类的类型。即,定义父类型的引用可以指向子类的对象。看如下代码所示:1. class Foo 2. int value;3. public void f() 4. Foo(int value) 5. this.value = value;6. 7. 8. class Goo extends Foo 9. int num;10. public void g() 11. Goo(int value, int num) 12. super(value);13. this.num = num14. 15. 16. class Test public static void main(St
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 木材与人类生活的密切关系考核试卷
- 医药制造业新兴技术应用与发展趋势考核试卷
- 煤炭加工煤炭电厂电力供应技术考核试卷
- 摩托车与先进制造技术考核试卷
- 汽车发动机变速器的设计与优化考核试卷
- 电机在农业灌溉的自动化控制考核试卷
- DB11-T 257-2021 籽粒玉米生产技术规程
- 春节消防课件教学课件
- 新员工流程培训总结
- 会计新员工入职培训总结报告
- 多属性效用函数的理论多目标决策问题的非劣解课件
- 《过新年》教学设计
- 施乐打印机M225M228中文说明书
- 高中语文学科核心素养和语文教学课件
- 沪科版九年级物理 (电阻和变阻器)探究电路教育教学课件
- 内部审计工作手册
- 8.12天津滨海新区爆炸事故带来的工程伦理思考
- 德育高级教师职称评审答辩教育理论题目与答案
- 语文二年级下册教学资料汇编:整本书:《小猪变形记》整本书指导
- 三通一平施工组织设计
- 第二语言习得研究期末复习题
评论
0/150
提交评论