好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

Java对象与内存管理机制.doc

7页
  • 卖家[上传人]:206****923
  • 文档编号:41711545
  • 上传时间:2018-05-30
  • 文档格式:DOC
  • 文档大小:128.50KB
  • / 7 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 1.实例变量和类变量的内存分配实例变量和类变量的内存分配 类变量 :使用 static 修饰的成员变量是类变量,属于该类本身 实例变量:没有使用 static 修饰的成员变量是实例变量,属于该类的实例 由于同一个 JVM 内每个累只对应一个 Class 对象,因此同一个 JVM 内的一个类的类变量 只需一块内存空间 对于实例变量而言,该类没创建一次实例,就需要为实例变量分配一块内存空间,所以, 程序中有几个实例,实例变量就需要几块内存空间 2.类变量的初始化时机总是出于实例变量的初始化之前类变量的初始化时机总是出于实例变量的初始化之前 我们先看下下面三段代码: 1)因为两个实例变量都是在创建变量的时候才开始分配空间,此时 num2还没有分配,所 以前向引用就会出现编译错误2)因为两个类变量在 JVM 加载类的时候分配空间,此时 num2还没有分配,所以前向引用 就出现变异错误3)因为类变量 num2在 JVM 加载类的时候空间已经分配好,而 num 在创建实例的时候踩 分配空间,此时 num2已经分配成功了,所以 num 前向引用成功由上面三段代码块就可以验证得:类变量的初始化时机总是出于实例变量的初始化之前 3.Java 对象的初始化方式及其执行顺序对象的初始化方式及其执行顺序 Java 对象的初始化方式有三种:1)构造器 2)初始化块 3)定义变量时指定初始化值 如果这三种初始化方式同时出现,也要注意,他们也有一个执行顺序的规定: 1)静态初始化块只在类第一次创建对象的时候运行一次,后面就不会再运行,而类在每次 创建对象时,非静态初始化块总是会运行一次。

      12int num = num2 + 3; //非法前向引用,会报错 int num2 = 2 12static int num = num2 + 3; //非法前向引用,会报错 tatic int num2 = 2 12int num = num2 + 3; //正确使用 static int num2 = 2; 运行结果:2)构造器每次创建对象时,构造器必然有执行的机会 ,此时,非静态初始化块必定也将获得机会并且运行在构造器之前1234567891011121314151617public class Test{ static { System.out.println(“执行---静态初始化代码块.“); } { System.out.println(“执行---非静态初始化代码块.“); } public static void main(String[] args) { for (int i = 1; i <= 2; i++) { System.out.println(“创建第 “ + i + “ 个对象“); new Test(); System.out.println(); } } } 运行结果: 3)定义变量时指定的初始化值和初始化块中指定的初始值的执行顺序与他们在源程序中的 排列顺序相同。

      验证代码一:123456789101112131415161718public class Test{ { System.out.println(“执行---非静态初始化代码块.“); } public Test() { System.out.println(“执行---构造器.“); } public static void main(String[] args) { for (int i = 1; i <= 2; i++) { System.out.println(“创建第 “ + i + “ 个对象“); new Test(); System.out.println(); } } } 运行结果 验证代码二 :12345678910111213141516public class Test{ String i = “定义变量时指定的初始化值“; { i = “初始化块中指定的初始值“; } public static void main(String[] args) { for (int i = 1; i <= 2; i++) { System.out.println(“创建第 “ + i + “ 个对象“); System.out.println(new Test().i); System.out.println(); } } } 123456789101112131415public class Test{ { i = “初始化块中指定的初始值“; } String i = “定义变量时指定的初始化值“; public static void main(String[] args) { for (int i = 1; i <= 2; i++) { System.out.println(“创建第 “ + i + “ 个对象“); System.out.println(new Test().i); System.out.println(); } } }运行结果: 4.关于父子实例的内存控制关于父子实例的内存控制 (一般情况下是不用内部类来验证的,但是都是一样的啦,我偷懒下,所以使用了内部类, 大家原谅哈) 1)当子类重写父类方法后,父类表面上只是调用属于自己的被子类重写的方法。

      161234567891011121314151617181920212223242526public class Test{ class Base { Base() { this.info(); } public void info() { System.out.println(“Base“); } public void getInfo() { info(); } } public class Child extends Base{ @Override public void info() { System.out.println(“Child“); } } public static void main(String[] args) { Test test = new Test(); Base base = test.new Child(); base.info(); base.getInfo(); } } 运行结果:2)上述是属于多态中方法的体现,但是方法有多态,实例变量无多态 解释下“方法有多态,变量无多态”这句话:意思是,不管怎样,父类表面上只是调用属于 自己的被子类重写的方法。

      而变量不一样,假设父类和子类都有同 一个变量名的实例变量, 向上转型后,通过父类访问的实例变量得到的值是自身的而非子类的向下转型后,通过 子类访问的实例变量得到的值是自身的而非父类 的 很多书上或教学视频上都讲,创建一个子类对象的时候,Java 会顺着继承结构往上一直找 到 Object,然后从 Object 开始往下依次执行构造函数先执行父类的构造函数,然后在 其子类中会创建一个成员变量指向他的父类其实这个说法是错误的,系统并不会真正的 去创建父类对 象,只是在子类对象中不仅保存了本身的实例变量,还有它父类的全部实例变量运行结果: 1234567891011121314151617public class Test{ class Base { //父类 int i = 2; } public class Child extends Base{ //子类 int i = 20; } public static void main(String[] args) { Test test = new Test(); Child child = test.new Child(); Base base = child; System.out.println(“ Base.i : “ + base.i); System.out.println(“Child.i : “ + child.i); } } 5.final 修饰符修饰符 final 变来那个在编译时就被确定下来了,相当于一个直接量。

      1)final 修饰的实例变量赋值时机: 定义 final 实例变量时 指定初始值 在非静态初始化模块中为 final 实例变量指定的初始值 在构造器中为 final 实例变量指定初始值 2)final 修饰的类变量赋值时机: 定义 final 类变量时指定初始值 在静态初始化模块中为 final 实例变量指定的初始值。

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.