`

疯狂Java 程序员基本功的16课(对象与内存的控制)心得(一)

    博客分类:
  • j2se
 
阅读更多

下面的心得只是根据这本书的案例和根据我自己角度和理解,如果你没看过可以和我一起学习,如果您看过这本书,发现我说的有不对地方请指出,共同学习!

第一课 :暂时先略过。以后补

第二课:对象与内存的控制

  1.           类变量和实例变量:如果初始化两个变量,这两个变量同为类变量或同为实例变量,那么在实例化时要注意实例化的顺序,
               // 下面实例变量初始化,将提示非法向前引用
    	 
    	int first = second-1;
    	int second = 2;
    	// 下面类变量量初始化,将提示非法向前引用
    	static int third = four-1;
    	static int four = 4;
    	//下面正常状态
    	int six = seven-1;
    	static int seven = 7; 
     上面得粗体字是正常的状态,因为静态变量(类变量)的初始化总在实例变量初始化前。不懂的可以先记住,后面有详解

            类变量和实例变量的属性,通过名字可以就可以知道,实例变量只能通过类的实例对象去访问;类变量就是属于类,直接可以通过类去访问,虽然类变量也可以通过类实例化的对象去访问,但底层最后还是通过类去访问的。所以我个人认为如果直接用类去访问类变量要比通过实例化的类对象去访问类变量的效率要高一些。

          实例变量的初始化时机:对于实例变量而言,它属于Java对象本身,每次创建java对象时都需要为实力变量分配存储空间,并执行初始化操作。从语法角度我们可以从三个角度初始化实例变量,如下:

 

 

 定义实例变量时指定初始值
	非静态初始化块中对实例变量指定初始化值
	在构造器中对实例变量指定初始化值

 其中第1种和第2种方式要早于第3种(在构造器中初始化),第1和2种初始化的方式地位是平等的,所以执行初始化顺序按照在源程序中排列的顺序相同。看下面的代码,试想一下你的结果?

 

class Cat{
	String name;
	public Cat(String string) {
		System.out.println("执行构造器初始化");
		this.name = string;
	}
	{
		System.out.println("执行非静态代码块");
		weight = 2.0;
	}
	//定义时指定初始值
	double weight = 4.0;
	public String toString() {
		return "age="+name+",weight="+weight;
	}
}

public class Test {
	public static void main(String[] args) {
		Cat cat = new Cat("jiafei");
		System.out.println(cat);
	}
}
//执行结果如下:
//			执行非静态代码块
//			执行构造器初始化
//			age=jiafei,weight=4.0

 和你想的结果一样么?结果一样证明你比我强啊,我在这里有个疑惑:就是weight的初始化的代码块和直接初始化,定义在代码块后但没报错?其实看过这我才懂真正的原因。其实这两种方式前面说过是平等的地位,经过编译后他们都在构造器初始化的,对于类中的double weight = 4.0;实际分成2次执行步骤:

double weight;//创建java对象时系统为实例变量分配内存空间。
weight = 4.0//这条语句将会被提到java的构造器中执行

 下面看看这个简单的例子,并用javap -c JavaToolTest命令查看编译的原理如下:

public class JavapToolTest {
	int count = 11;
	{
		count = 22;
	}
	public JavapToolTest() {
		System.out.println(count);
	}
	public JavapToolTest(String name) {
		System.out.println(name);
	}
}
对编译后的JavaToolTest.class运行
javap -c JavaToolTest则看到
D:\software>javap -c  -classpath D:\software JavapToolTest
Compiled from "JavapToolTest.java"
public class JavapToolTest extends java.lang.Object{
int count;
public JavapToolTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   bipush  11
   7:   putfield        #2; //Field count:I
   10:  aload_0
   11:  bipush  22
   13:  putfield        #2; //Field count:I
   16:  getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   19:  aload_0
   20:  getfield        #2; //Field count:I
   23:  invokevirtual   #4; //Method java/io/PrintStream.println:(I)V
   26:  return
public JavapToolTest(java.lang.String);
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   bipush  11
   7:   putfield        #2; //Field count:I
   10:  aload_0
   11:  bipush  22
   13:  putfield        #2; //Field count:I
   16:  getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   19:  aload_1
   20:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
   23:  return
}

 上面的javap中的粗体表示实例变量都在每个构造器中初始化,而且总位于构造器中所有语句之前。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics