`
qzr
  • 浏览: 2741 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

java 传值 常量池 构造函数 String (札记)

阅读更多

最近在读周志明的《深入理解Java虚拟机2》和《Pratical Java》,结合面试的时候常常考到的一些问题,做一下笔记。


1、Java值传递 by value not by reference

《Pratical Java》第一个问题讲到的就是这个问题,Java中传值传的是值而不是引用。注意,这里所说的值不止普通值,还包括引用值。比如传应用对象的时候,传的就是一份copy的reference。这样说起来有些拗口,也有些强词夺理。但这不是我要关注的,我要关注的是传值过后对原值的影响。

例如

static void changePass(StringBuffer psf1,StringBuffer psf2){
    psf1.append(psf2);
    psf2 = psf1;	
}

public static void main(String[] args) {
    StringBuffer sf1 = new StringBuffer("A");
    StringBuffer sf2 = new StringBuffer("B");
    changePass(sf1, sf2);
    System.out.println(sf1+":"+sf2); //AB:B
}
从打印的值可以看出,sf1的值改变了,而sf2的值没有变。通过打印出psf1和psf2前后的hashCode,可以看出,传进去的时候,psf1==sf1 ,psf2==sf2

然后经过两行代码后 psf1==psf2 了。结合打印结果,我大胆地断言,Java传的是值而不是reference!

psf1装有sf1的引用,他利用这个引用去修改了sf1,这个很好理解。而psf2经过赋值后,的确装的也是psf1的引用,可是,这跟sf2没有半毛钱关系,它只是传进来的一份复制品而已。所以,但函数回到调用函数的时候,sf1还是它自己。

2、String这个变态!

String在Java中我觉得很像太监,半男不女。是没错,它是引用类型,但是它的+语句会让你崩溃。音乐又有一点基本类型的特点,最要命的是,它居然和int、float这些基本类型一样有常量池!!!好吧,常量池也是个变态,常量池位于方法区(Method Area)。

Java认为,这些常量之类的东西,你们总会用重复的,所以搞了个常量池,凡是基本类型,直接去常量池找,找不到再给你弄一个。这时候String也来凑热闹,凡是用+号或者“”来赋值的String都先去常量池找,有合适的直接把引用返回给它。如果用new 来实例的话,那就肯定是在堆中了,就不去常量池找了。

3、构造函数的初始化过程

class Super {
	int i = 10;
	Super(){
		print();
		i = 20;
	}
	
	void print(){
		System.out.print(i);
	}
}

public class Sub extends Super{
	int j = 30;
	
	public Sub() {
		print();
		j = 40;
	}
	
	void print(){
		System.out.print(j);
		
	}
	
	public static void main(String[] args) {
		System.out.print(new Sub().j);//03040
	}
}

从这里的打印结果就可以看出,好像并不是那么简单。我debug跟踪调试发现了两点:

甲、当子类运行到构造名时,先去父类运行构造函数,同理,父类如果有爷爷类,那么运行到父类的构造名的时候,先去爷爷类运行构造函数,直到运行到java.lang.Object类.然后初始化数据,运行构造本体,类似递归。

乙、在父类的构造函数中,试图运行已被子类覆盖的程序的时候,不好意思,运行的是子类的。

以上,与君共赏!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics