深化Java基础之——对象与内存控制
Java是一门面向对象语言,作为Java程序员,对于对象的使用一定不陌生,本文就总结一下创建对象时发生的一些事情。
1.实例变量和类变量
看到这个标题大家一定想到的是static关键字,没错,被static关键字修饰的变量,方法,内部类,初始化块,这些都属于类,而不具体属于某个实例对象,可以直接通过类名来调用。关于static可能造成的内存泄漏,在后面的JVM文章里总结。这里我就简单通过两个程序总结一下类成员和实例成员的区别,以及创建一个对象后初始化的顺序。
实例变量属于对象,每实例化一个对象,就会为其在内存中分配一块空间。类变量只会在第一次使用该类时为其分配一份内存空间,无论创建了多少个该类的对象,static变量永远只有一份内存空间。一个类在使用之前,就会在JVM中对该类进行加载-连接-初始化,在连接时就会给类变量分配相应的内存空间。
1 public class B extends A { 2 public int m = method3(); 3 public static int n = method4(); 4 public int t = 0; 5 public B(){ 6 System.out.println(4); 7 } 8 public int method3(){ 9 System.out.println(5); 10 return 5; 11 } 12 public static int method4(){ 13 System.out.println(6); 14 return 6; 15 } 16 public static void main(String[] args) { 17 System.out.println(7); 18 A a = new B(); 19 } 20 } 21 22 class A { 23 public int i = method(); 24 public static int j = method2(); 25 public int k = 0; 26 public A(){ 27 System.out.println(1); 28 } 29 public int method(){ 30 System.out.println(2); 31 return 2; 32 } 33 public static int method2(){ 34 System.out.println(3); 35 return 3; 36 } 37 }
A、7 3 2 1 6 4 5 B、3 6 7 2 1 5 4 C、7 3 6 2 1 5 4 D、3 2 1 7 6 5 4
看看上述代码的输出结果应该选哪个呢?
让我们一步一步来分析:A类是B类的父类,在执行程序时,A类先被加载,并且为其类变量分配内存空间,所以先为24行的 j 分配内存,初始化为methond2()方法的返回值,这里的method2()也必须被static修饰,才能被调用,所以先输出3;同理,接下来为B类的类变量分配空间,输出6;然后执行16行main()方法,输出7;实例化B类的对象,先执行其父类(A)的非静态初始化(代码23行),method()方法输出2;然后是父类(A)的构造方法,输出1;然后是B类同理,依次输出5和4,程序结束,所以最终答案是B。
这个代码大家可以复制下来进行单步debug来细细体会。
再来看一个有趣的代码,细细品味。
1 public class PriceTest { 2 3 public static void main(String[] args) { 4 System.out.println(Price.instance.currentPrice); 5 //显示的创建Price对象 6 Price p = new Price(2.8); 7 System.out.println(p.currentPrice); 8 } 9 } 10 11 class Price{ 12 //类变量 13 final static Price instance = new Price(2.8); 14 //类变量 15 static double initPrice = 20; 16 //实例变量 17 double currentPrice; 18 public Price(double discount){ 19 currentPrice = initPrice - discount; 20 } 21 }
上述代码输出了两次currentPrice,而且都是通过new Price(2.8)来创建实例,看起来应该是输出两次17.2,亲自运行一下这个代码,会发现结果却是-2.8和17.2。
下面从内存层面上来看看到底发生了什么,当然,首先还是先为Price类的类变量分配内存空间,这个时候两个static变量instance和initPrice值为null和0.0,接下来按这个顺序为它们初始化,instance的值为new Price(2.8),立即执行18行,所以这时的currentPrice是等于0.0 - 2.8的,instance初始化完毕,然后是initPrice初始化为20。所以第4行输出-2.8,执行第6行时,类变量initPrice已经为20,所以第7行输出17.2。

浙公网安备 33010602011771号