【Java编程思想】第五章 初始化和清理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chuxue1989/article/details/88064151

这里是我看编程思想的收获知识点,我已经知道的就不会写出来了,算是对我新知识点的回顾

一、成员初始化

class A{
	int i = 10;
	public A(int i){
		this.i = i;
	}
}

public static void main(String[] argus){
	A a = new A(20);
}

比如上面的i是如何初始化呢?
首先默认初始化: A的字节码加载带内存的时候基本类型会进行默认初始化,比如int会初始化成0.

类型 初始值
boolean false
char null
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0.0d

指定初始化: 在定义i的时候给予i初始值10,代码块也能同样完成这样的功能。
构造器初始化: 通过构造函数初始化

二、this关键字

java初始化其中最常见的一种形式是构造函数,如果一个方法中有多个构造函数,多个构造函数如何相互调用呢?
周所周知字节码是存在方法区中的,当一个对象调用方法的时候,把方法区中翻译的字节码压入堆栈,执行方法的过程中是要操作数据的,那么如何知道那个对象的数据呢?

class A{
	int i;
	public A(int i){
		this.i = i;
	}
	public int add(int x){
		return x+i;
	}
}

public static void main(String[] argus){
	A a = new A(10);
	A aa = new A(20);
	a.add(100);
	aa.add(900);
}

比如上面代码调用a.add的时候如果知道i值是多少呢?其实他的内部原理是这样的。

a.add(100);
可以翻译成=====>
add(this,100);其中this代表a引用,所以在方法
public int add(int x){
		return x+i;//i其实是this.i 也就是a.i = 10
}

所以this就是当前对象的引用

三、清理之finalize

首先几个比较重要的概念

  • 对象可能不被垃圾回收器回收
  • 垃圾回收不等于C++析构
  • 垃圾回收至于内存有关

垃圾回收器准备好要回收对象占用的存储空间的时候,会首先调用对象的finalize方法,等下一次垃圾回收器发生回收动作的时候,才会真正的回收对象占用的内存

其中我最大的疑惑是:我有个垃圾回收为什么还要调用finalize呢,而且还是定义在Object中。
垃圾回收器只会回收由new产生的对象,而finalize是用来调用本地方法回收非new对象的特殊内存。到底特殊内存是怎么产生的呢?这种情况主要是使用本地方法来产生的内存,所以需要在finalize中调用本地方法来回收内存

程序员基本很少有可能会使用这个方法

四、垃圾回收简单介绍

更详细的垃圾回收我会在看过jvm的高级特性后详细阐述。这次我只写出大致的原理

扫描二维码关注公众号,回复: 5519903 查看本文章

4.1、引用计数法

每个对象都含有一个引用计数器,当有引用连接到对象时,计数器+1,当引用离开作用域时候或者引用被职位null,计数器-1。这样等垃圾回收器工作的时候,寻找那些计数器为0的就行。
缺点:
每次循环判断所有的对象,速度缓慢,而且无法解决对象循环引用的问题。

class A{
	private B b;
	public void setB(B b){
		this.b = b;
	}
}

class B{
	private A a;
	public void setA(A a){
		this.a = a;
	}
}

public static void main(String[] argus){
	A a = new A();
	B b= new B();
	
	a.setB(b);
	b.setA(a);
	
	a=null;
	b=null;
}

比如上面的例子,执行到最后对象a和b都无法访问到了,但是因为都有彼此的引用使得计数器不为0,这样永远也回收不了。

4.2、stop-and-copy

对任何活的对象,一定能追溯到其存货在堆栈中或者静态区域中的引用。由此从堆栈或者静态区域开始遍历所有引用就能找到所有活着的对象。
找到所有活着的对象的时候,先把程序暂停,然后将或者的对象按照顺序放到另外一个堆中,剩下的都是垃圾,可以及时清理掉。
缺点:
如果程序趋于稳定,存货时间长,那么每次基本上90%的对象都是活的,那么每次都把90%对象拷贝到另外一个堆中,浪费很大的性能。所以这个方式只适合新生代:存活时间短的对象
而且还要有两个堆,浪费内存。

4.3、mark-and-sweep

针对上一种方式的缺点,出现另外一种方式,那就是如果找到一个活的对象,就标记他,等内存快满了,垃圾回收器工作的时候就把没有标记的清除,随后可能需要再次整理整齐。
这种方式很明显适合垃圾很少的情况,也就是老年代:存货时间长的对象。

4.4、自适应

java虚拟机会进行监视如果所有对象都很稳定,那么就切换成mark-and-sweep,,同样java虚拟机会跟踪mark-and-sweep的效果,如果产生很多碎片就切换成stop-and-copy

猜你喜欢

转载自blog.csdn.net/chuxue1989/article/details/88064151
今日推荐