有一道java面试题,大概是这样的:
public class Test {
public static void main(String args[]){
String s;
System.out.println("s="+s);
}
}
看起来真的很简单,那么答案是什么呢?编译不通过。
如果在笔试现场有IDE能让你使用,恐怕再简单不过了,答案自动就告诉你了。可惜笔试的时候根本没有电脑,而且更多的程序都要靠自己笔写。
那么回过头来看一下为什么编译不通过呢?其实java里的一切都被视为对象,操纵的标识符实际上是对象的一个“引用”(reference)。怎么来理解这句话呢,在《Thinking in java》中,作者有如下精妙比喻:可以将这一场景想像成用遥控器(引用)来操纵电视机(对象)。String s便是产生了一个遥控器,若给其赋值则绑定到了某个具体的电视机上了。当然,即使没有电视机,遥控器也可以存在,但是当向遥控器发送消息时,若电视机不存在,则会返回错误了。因此,一种更安全的做法是:创建一个引用的同时便进行初始化的操作。
注意:若类的某个成员变量是基本数据类型,即使没有进行初始化,java也会给其一个默认值。那么为什么上面这个程序中的s没有被附上初始值呢?最主要的原因是,只有当变量作为类的成员使用时,java才确保为其附上初始值。在这里,尽管String不是java的基本数据类型,不过若通过类的成员调用时,还是可以被附上null这个初始值。
既然要创建对象,那么程序运行时,对象是怎么进行放置安排的呢?特别是在内存中又是怎样分配的呢?有6个不同的地方可以存储数据:
1、寄存器:(最快,因为它在处理器的内部)
2、堆栈:(位于通用RAM中,随机访问存储器,速度仅次于寄存器)虽然某些java数据存储于堆栈中,特别是对象引用,但是java对象本身并不存储于其中,因为其需要让编译器事先知道存储在堆栈内所有数据的确切大小和生命周期,生成相应代码,以便上下移动堆栈指针来进行分配和释放内存。
3、堆:一种通用的内存池(也位于RAM区),用于存放所有的java对象。使用堆比使用堆栈有更大的灵活性:当需要创建一个对象时,只需用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。当然为了这种灵活性,付出了相应的代价:花费了比在堆栈中进行存储分配更多的时间。
4、静态存储:“静态”是指“在固定的位置”(尽管也在RAM中)。静态存储里存放的是程序运行时一直存在的数据。用关键字static来表示某个对象的特定元素是静态的,但java对象本身从来不会存放在静态的存储空间里。
5、常量存储
6、非RAM存储
对于5和6,书中虽然有解释,但是自己没有什么特别体会,所以先暂时不写了。
public class Test {
public static void main(String args[]){
String s;
System.out.println("s="+s);
}
}
看起来真的很简单,那么答案是什么呢?编译不通过。
如果在笔试现场有IDE能让你使用,恐怕再简单不过了,答案自动就告诉你了。可惜笔试的时候根本没有电脑,而且更多的程序都要靠自己笔写。
那么回过头来看一下为什么编译不通过呢?其实java里的一切都被视为对象,操纵的标识符实际上是对象的一个“引用”(reference)。怎么来理解这句话呢,在《Thinking in java》中,作者有如下精妙比喻:可以将这一场景想像成用遥控器(引用)来操纵电视机(对象)。String s便是产生了一个遥控器,若给其赋值则绑定到了某个具体的电视机上了。当然,即使没有电视机,遥控器也可以存在,但是当向遥控器发送消息时,若电视机不存在,则会返回错误了。因此,一种更安全的做法是:创建一个引用的同时便进行初始化的操作。
注意:若类的某个成员变量是基本数据类型,即使没有进行初始化,java也会给其一个默认值。那么为什么上面这个程序中的s没有被附上初始值呢?最主要的原因是,只有当变量作为类的成员使用时,java才确保为其附上初始值。在这里,尽管String不是java的基本数据类型,不过若通过类的成员调用时,还是可以被附上null这个初始值。
既然要创建对象,那么程序运行时,对象是怎么进行放置安排的呢?特别是在内存中又是怎样分配的呢?有6个不同的地方可以存储数据:
1、寄存器:(最快,因为它在处理器的内部)
2、堆栈:(位于通用RAM中,随机访问存储器,速度仅次于寄存器)虽然某些java数据存储于堆栈中,特别是对象引用,但是java对象本身并不存储于其中,因为其需要让编译器事先知道存储在堆栈内所有数据的确切大小和生命周期,生成相应代码,以便上下移动堆栈指针来进行分配和释放内存。
3、堆:一种通用的内存池(也位于RAM区),用于存放所有的java对象。使用堆比使用堆栈有更大的灵活性:当需要创建一个对象时,只需用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。当然为了这种灵活性,付出了相应的代价:花费了比在堆栈中进行存储分配更多的时间。
4、静态存储:“静态”是指“在固定的位置”(尽管也在RAM中)。静态存储里存放的是程序运行时一直存在的数据。用关键字static来表示某个对象的特定元素是静态的,但java对象本身从来不会存放在静态的存储空间里。
5、常量存储
6、非RAM存储
对于5和6,书中虽然有解释,但是自己没有什么特别体会,所以先暂时不写了。