对象
1. 对象的引用
每种编程语言都有自己操纵内存中的元素的方式,程序员必须要注意处理的数据类型是什么,是直接操作元素还是基于某种特殊的语法格式间接表示来操作对象,例如C++中就是使用指针。
在Java中一切都是对象,因此采用单一固定的语法。尽管可以看作对象,但正在操作的标识符实际上只是对象的一个“引用”。
当拥有一个引用,却不一定要和一个对象关联,例如:
String s;
这里只是得到一个引用,它并不是一个对象。
2. 对象的存储
Java程序运行期间,有五个不同地方可以存放数据:
寄存器。这是最快的存储区,位于处理器内部,程序员不能控制寄存器,也感觉不到寄存器的存在。
堆栈。位于通用的RAM中,通过“堆栈指针”来进行操作,若堆栈指针向下移动,则分配新的内存,若向上移动,则释放内存。创建程序时,Java系统必须知道存储在堆栈中的所有项的确切生命周期,以便上下移动指针,这回限制程序的灵活性,某些数据存储在堆栈中,比如对象的引用,但是对象并不存储在堆栈中。j ava基本类型也直接存放于堆栈中。
堆。一种通用的内存池,也位于RAM区。所有的Java对象存放于其中,对不同于堆栈的是,编译器不需要知道堆中存储的数据的存活时间是多少,这回带来灵活性,但分配存储空间和清理需要更多的时间。
常量存储。常量可以直接存放在程序代码中,因为常量永远不会改变。
非RAM存储。
3.对象的作用域
java对象不具备和基本类型一样的生命周期,当用new关键字创建一个对象后,它可以存活于作用域之外。
{
String s = new String("");
}
引用s在作用域终点就消失,然而s指向的String对象任然继续占据内存空间。
4. 类的基本成员的默认值
若类的某个成员是基本数据类型,即,使没有进行初始化,Java也会确保它有一个默认值。变量也只有类的成员使用时,Java才确保给定其一个默认值,以确保那些基本类型的成员变量得到初始化,防止程序产生错误。但是默认值对用户的程序来说可能是不对的,所以最好的方式是明确的进行初始化。
上述给定默认值的方式并不适用于方法内的局部变量,如果在某个方法中有如下语句:
int x;
那么x的值是任意值(这和C/C++是一样的),不会自动初始化为0,所以在使用这个变量x前,先要的对其进行初始化,否则编译器会检查出这是个错误。
Java没有sizeof操作符
在C和C++中通过sizeof运算符可以得知数据项分配的字节数。在C、C++中需要使用sizeof运算符的最大原因是为了移植,不同数据类型在不同的机器上可能有不同大小表示。
但是在Java中所有数据类型在所有机器上都是固定的。
this的使用
在方法内部使用:
如果用同一个类创建了两个对象o1和o2,同一个方法如何知道是哪个对象在调用自己呢?
public class Main{
public static void main(String[] args){
Type o1 = new Type(1), o2=new Type(2);
o1.f(1);
o2.f(2);
}
}
编译器做了一些幕后工作,它把“调用这个方法的对象的引用”暗自当作方法的第一个参数传递给方法,看起来就像这样:
o1.f(o1, 1);
o2.f(o2, 2);
当然,代码并不能这样编写,但这表示了实际放生的事情。如果要在方法内部拿到这个看不见的对象引用,则可以使用专门的关键:this。this只能在方法的内部使用,表示“调用此方法的那个对象”的引用。
在构造器中使用:
如果类中有多个构造器,有时需要在一个构造器中调用另一个构造器。当在this后面加上参数列表后就能做到。但只能位于构造器的第一条语句。
如果方法的参数名与类中的某个成员名相同,也可以使用this来屏蔽方法的参数名。