最近在读周志明的《深入理解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类.然后初始化数据,运行构造本体,类似递归。
乙、在父类的构造函数中,试图运行已被子类覆盖的程序的时候,不好意思,运行的是子类的。
以上,与君共赏!
分享到:
相关推荐
8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8.java构造函数.zip8....
看了些窗体传值的例题都是用构造函数 可我觉得构造函数想实现即时传值好象不行 呵呵,我总是理解不了构造函数(菜吧) 我所以就想了这样个办法来实现传值 using System; using System.Collections.Generic; using ...
C++实现 类string的 普通构造函数, 拷贝构造函数 析构函数 和赋值函数
String int 字符串常量池 包装类型 函数参数 值传递引用传递 的 内存分配例子——源码 public static void fun_ref (Ref_test ref_out){ Ref_test ref_in=new Ref_test(); ref_in.s1="in"; //ref_out.s1=...
详细介绍了构造函数、复制构造函数、拷贝构造函数之间的区别
创建一个子类的对象实例的时候,必先调用父类的无参数的构造函数(默认构造函数),假如父类有带参数的构造函数,那么系统将不会给它创建无参数的构造函数,这时,子类在实例化的时候,因为找不到父类的默认构造函数...
C#三种窗体之间传值全局变量、构造函数、委托,思路:构造函数和委托传递多个参数,可考虑将多个变量封装集合或者结构体,传递集合或结构体即可。
编写类String的构造函数,包括构造函数,析构函数,拷贝构造和赋值函数
每个类都具有构造函数和析构函数。其中,构造函数在定义对象时被调用,析构函数在对象释放时被调用。如果用户没有提供构造函数和析构函数,系统将提供默认的构造函数和析构函数。 1.构造函数 构造函数是一个与类同名...
问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使...
构建一个类Point,它提供两个公有的构造函数,一个没有参数的Point构造函数和一个有两个double参数的构造函数。另外在该类中提供一个静态方法计算两个点的直线距离,传入参数为两个Point类实例。然后设计一个测试类...
c#析构构造函数c#析构构造函数c#析构构造函数c#析构构造函数
构造函数与默认构造函数的声明、定义、应用、比较
本程序包含构造函数和析构函数,可以把构造函数和析构函数的作用区分开
类string构造函数的巧用
在Java中,构造函数的访问级别通常是public, 它提供了一个构造该类对象的接口。可是你知不知道,把构造函数的级别设为private, 有一些特别用处。
C++\测试 对象成员构造函数、基类构造函数、派生类本身的构造函数 的先后顺序.rar
java中的构造代码块和构造函数.pdf
map使用std::map, CArray,int> > 错误, 解决: 重写CArray, 重载构造函数并加const 添加操作 operator =