JavaBase:生命周期

初始化

构造器

默认构造器

  • 当在类中没有写构造器的时候,编译器会认为你忘记了这件事情,默认为你加上一个无参的构造器。
  • 当自己写了构造器后,编译器认为你知道自己想要什么,于是认为你不需要编译器的帮助,因此,需要自己选择写或不写无参构造器

使用this和super

  • this可以帮助调用同一个类的其他构造器
  • super可以调用父类的构造器
  • 它们必须是第一条语句
  • this与super不可兼得,因为他们必须是第一条语句
  • 但是可以曲线救国

使用初始化块

1
2
3
4
5
6
//该静态块会在构造方法执行前执行
//只要构造类的对象,这些方法就会执行
{
id=nextId;
nextId++;
}

关键字

this

  • 只在必要的地方使用this,可以便于阅读
  • this在方法中表示操作该方法的对象,并且方法可以返回一个this
    return this
  • 可以实现一种x.getthis().getthis().print();
  • 即多次递归调用

super

static

它是静态的,意味着不能加载动态资源,即不能加载对象的属性以及非静态的资源

静态资源的初始化

  • 当没有赋初值,静态资源会获得基本类型的标准初值,例如int为0,引用为null
  • 创建时间:在创建第一个table对象,或第一次加载类,或第一次访问静态资源
  • 初始化顺序:
  1. 先静态对象,即类中的static的资源
  2. 后非静态对象。

显式的静态初始化

使用静态块,将所有的静态语句组织起来

static {
  i=47;
  h=50;
}

数组初始化

初始

int[] a或 int a[]
  • 为什么不能确定大小?
  • 因为初始化的只是对对象的一个引用,并没有分配内存空间,只是表明这是一个数组对象,引用哪来的大小

初始化的方法

int[] a= new int(5);//方法1
Integer[] a ={ //方法2
  new Integer(1),
  new Integer(2),
};
Integer[] b=new Integer[]{ //方法3
  new Integer(1),
  new Integer(2),     
};

可变参数列表

实现

public void printArr(Object ... args){
  for (Object obj : args)
    System.out.println(obj + " ");
}

终结条件

  • finalize对象终结条件的验证if()
  • System.gc()强制执行终结动作

清理

牢记

  1. 垃圾回收只与内存有关
  2. 对象可能不会被垃圾回收
  3. 垃圾回收不等于”析构”(C++)

垃圾回收器的工作范围

  • 垃圾回收器只会回收通过new分配的内存
  • 垃圾回收只与内存有关
  • 对象可能不会被垃圾回收
  • 垃圾回收或者终结,不一定发生,如果JVM未面临内存耗尽,不会浪费时间去执行垃圾回收以恢复内存

特殊情况

  • 获得一块非new的特殊内存
  • 例如对象将自己绘制到了屏幕上,需要在对象销毁时候,将自己擦除
  • 由于不是new得到的内存,因此垃圾回收器无法处理

解决方案:定义finalize()方法

  • finalize必须与内存相关,因为垃圾回收器只与内存有关
  • 垃圾回收期准备释放对象的内存
  • 调用finalize方法
  • 在下一次垃圾回收动作发生时,真正回收对象占用的内存

垃圾回收器的工作方式

引用计数法

  • 当有引用连接至对象时,引用计数+1
  • 当引用离开作用域或者被置为null,引用计数-1
  • 缺陷
  • 如果对象间存在循环引用,可能出现对象应该被回收,但引用计数不为0
  • 工作量极大,速度极慢

对任何活的对象,一定能最终追溯到其存活的堆栈或静态存储区之中的引用

  • 实现方法
  • 停止-复制法
  • 暂停程序运行,将所有的活对象复制到一个新的堆内,没有被复制的都是垃圾,在新堆上,对象紧密排列
  • 效率低,内存开销大
  • 当只有少量的垃圾,较为浪费
  • 标记清扫法
  • 每找到一个活的对象,进行标记,没有被标记的被清扫
  • 自适应
  • JVM监视,如果所有对象很稳定,采用标记清扫,如果出现很多碎片,采用停止复制
  • 分代
  • 内存分配以块为单位
  • 大型对象会单独占用一个块
  • 每个块有相应代数记录是否存活
  • 垃圾回收器对上次回收动作后新分配的块进行整理,对处理大量短命的对象很有效果
  • 定期进行清扫,大型对象不会被清扫(代数增加),内涵小型对象的块会被复制整理
  • 即时编译器JIT
  • 将程序全部或者部分翻译成机器码
  • 当装载某个类
  • 寻找.class文件,将该文件字节码装入内存
  • ###有两种方案
  • JIT编译全部代码
  • 缺陷
  • 加载动作散落在整个程序生命周期
  • 增加可执行代码的长度,降低速度
  • ###方案二
  • 惰性评估
  • JIT只在必要的时候编译代码

###成员初始化

#构造器与垃圾收集器

  • 内存区域

    • 堆:对象的生存空间 实例变量–声明在类里面而不是方法里
    • 栈:方法调用和变量的生存的空间 局部变量
    • 在方法里使用Duck d=new Duck();d在栈里,因为他是对象的引用,d所引用的对象在堆里面
  • 方法进入栈的方式

  • 调用一个方法,方法会被放在调用栈的栈顶,

  • 如果该方法要调用另一个方法,则该另一个方法会放在原方法的上面

  • 放在栈上的方法是一个堆栈块,带有方法的状态\执行到哪一段程序及所有的局部变量

对象生命周期

  • 当对象的引用全部消失,以及无法取得对象的引用,那么符合垃圾回收器的条件
  • 对象引用可以是Null,但是对null操作是运行时异常,所有编译器没有问题