headfirst java ( 第 9 章 )

- 栈和堆

  当java虚拟机启动时, 它会从底层的操作系统取得一块内存, 并以此区段来执行java程序.

  栈: 主要用来保存方法和局部变量.

  堆: 保存所有对象.

  image

  实例变量存在于对象所属的堆空间上.

  编译器会根据实例变量所需要的空间分配, 例如int类型需要32位等等, 如果变量本身是个对象的引用, 那也没关系, 只是分配能够装下引用的

  空间就可以了, 至于该引用所指向的空间, 要看程序是否分配(即用 new 来创建对象), 例如: private Antenna ant; 只是创建了一个引用

  private Antenna ant = new Antenna(); 才是在堆内存中分配了空间, 并让ant指向该空间.

- 创建对象的奇迹

  创建对象分3步, 声明引用(指针), 创建对象, 将指针指向该对象, 那么第2步是怎么创建对象的呢?

  1. Duck myDuck = new Duck();  // 下划线对应 声明引用

  2. Duck myDuck = new Duck();  // 下划线对应 创建对象

  3. Duck myDuck = new Duck();  // 下划线对应 链接(指向)

  上边第2步实际上是调用构造函数, 构造函数看起来很像方法, 但是其实它不是方法, 前边有 new 关键字, 构造函数与类名相同, 且没有返回值

  构造函数的一项关键特征是它会在对象能够被赋值给引用之前就执行. 构造函数的主要用途是: 初始化对象,例如实例变量. 一般方法也可以与类

  同名, 但是必须有返回值. 构造函数不会被继承.

  一定要有不需要参数的构造函数. 习惯, 这样做是有好处的.

  如果你已经写了一个有参数的构造函数, 并且你需要一个没有参数的构造函数, 则你必须自己动手写.

  如果类有一个以上的构造函数, 则参数一定要不一样.( 参数的顺序和类型 )

  继承的关系: 执行 new 的指令是个重大事件, 它会启动构造函数连锁反应, 就算是抽象的类也有构造函数. 虽然你不能对抽象的类执行new操作

  单抽象的类还是父类, 因此它的构造函数会在具体子类创建出实例时执行.

  在构造函数中调用 supper调用父类构造函数的部分, 子类可能会根据父类的状态来继承方法(也就是父类的实例变量), 构造函数在执行的时候,

  第一件事是去执行它的父类的构造函数, 这会连锁应用到 Object这个类为止. 这是因为, 子类调用构造函数时, 会调用到父类的构造函数, 这

  时候子类构造函数会入栈, 父类构造函数再入栈, 而出栈时, 肯定是父类先出, 所以就是父类先执行, 子类后执行. 这里体现了为什么没有参数

  的构造函数十分重要, 就是当你定义子类时, 在子类的构造函数中, 你没有显示声明调用父类的某个构造函数, 例如 super(1); 那么编译器就

  会调用父类的默认构造函数( 即没有参数的构造函数), 而此时如果父类没有该构造函数, 系统就会报错, 所以类中最好要有一个没有参数的构造

  函数. 把父类想象成父母, 子类想象成孩子, 肯定是父母先出来, 没准孩子要使用父母的一些东西, 所以肯定是父母先出来.

  另外, 如果你在子类的构造函数中显示调用父类构造函数, 比如: supper(); 必须把这个语句放在构造函数的第一行( 这也是必须的, 要先有

  父母, 再有孩子, 这个顺序不能乱 )

  使用 this() 可以从某个构造函数调用同一个类得另外一个构造函数, this()只能用在构造函数中, 且必须是第一行语句. super()与this()

  不能兼得, 因为都要放在第一行.

- 对象生命周期

  对象的生命周期要看引用它的“引用”(指针)引用在,对象在,引用没有了,对象也就没有了

  局部变量:只会存活在声明该变量的方法中

  实例变量:与对象相同

- life 与 scope 的差别

  life: 只要变量的堆栈块还存在于堆栈上,局部变量就还活着,例如: public void doStuff() { boolean b = true;

  go(4); }

  public void go(int x) { int z = x + 24; crazy(); // 这里有更多代码 }

  public void crazy() { char c = ‘a’; } 以上程序在执行时,局部变量 b 始终在堆栈中,它始终活着(但是无法访问到)

  scope: 局部变量的范围只限于声明它方法之内,当此方法调用别的方法时,该变量还活着,但是不在scope范围内, 执行其他方法完毕返回时,

  范围也就跟着回来。

- 对象用完了以后就要抛弃,这样才能让垃圾收集器有东西可以回收,当最后一个引用消失时,对象就会变成可回收的(注意:只是变成可回收的,

  但是没有说已经回收,至于垃圾回收期什么时候回收,以后在说。),将引用变量设置成 null,就可以把对象变成可回收的,例如 z = null;

- 对象杀手1号(引用永久性的离开它的范围)

  例如:

  image

  image

  image

  image

- 对象杀手2号(引用被赋值到其他对象上)

  image

  image

  image

- 对象杀手3号(直接将引用设定为null)

  image

  image

  image

- java中的method存放在哪里?

  个人感觉: 应该是存放在栈,而且不是你建立一个对象,就把他的所有方法都存放在栈,而是,当程序使用到时,在栈分配内存,

  当然,首先要参考类得模板(方法的定义),然后再分配,调用完毕以后,就释放该栈中的内存,所以,method同实例变量不同,不是

  跟随对象的创建而在堆上分配的。

你可能感兴趣的:(first)