2.2.3 Java中的数组
几乎所有的程序设计语言都支持数组。
Java的主要目标之一是安全性,所以许多在C和C++里困扰程序员的问题在Java里不会再出现。
Java确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下标检查为代价的。
但由此换来的是安全性和效率的提高,因此付出的代价是值得的(并且Java有时可以优化这些操作)。
当创建一个数组对象时.实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null。……编译器也能确保基本数据类型的数组的初始化,因为它会将这种数组所占的内存全部置零。
2.3 永远不需要销毁对象
在大多数程序设计语言中,变量生命周期的概念,占据了程序设计工作中非常重要的部分。
变量需要存活多长时间?如果想要销毁对象,那什么时刻进行呢?
变量生命周期的混乱往往会导致大量的程序bug,本节将介绍Java是怎样替我们完成所有的清理工作,从而大大地简化这个问题的。
2.3.1 作用域
大多数过程型语言都有作用域(scope)的概念。作用域决定了在其内定义的变量名的可见性和生命周期。
在C、C++和Java中,作用域由花括号的位置决定。
在作用域里定义的变量只可用于作用域结束之前。
任何位于"//"之后到行末的文字都是注释。
缩排格式使Java代码更易于阅读。由于Java是一种自由格式(free-form)的语言,所以,空格、制表符、换行都不会影响程序的执行结果。
在C和C++里将一个较大作用域的变量“隐藏”起来的做法,在Java里是不允许的。
因为Java设计者认为这样做会导致程序混乱。
2.3.2 对象的作用域
Java对象不具备和基本类型一样的生命周期。当用new创建一个Java对象时,它可以存活于作用域之外。
在后继章节中,读者将会看到:在程序执行过程中,怎样传递和复制对象引用。
这样便带来一个有趣的问题。如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?这也是Java神奇之所在。
Java有一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。你根本不必担心内存回收的问题。
你只需要创建对象,一旦不再需要,它们就会自行消失。这样做就消除了这类编程问题(即“内存泄漏”)
2.4 创建新的数据类型:类
如果一切都是对象,那么是什么决定了某一类对象的外观与行为呢?换句话说,是什么确定了对象的类型?
大多数面向对象的程序设计语言习惯用关键字class来表示“我准备告诉你一种新类型的对象看起来像什么样子 ”。
在定义它的所有方法之前,还没有办法能让它去做更多的事情(也就是说,不能向它发送任何有意义的消息)。
2.2 必须由你创建所有对象
2.2.3 Java中的数组
几乎所有的程序设计语言都支持数组。在C和C++中使用数组是很危险的,因为C和C++中的数组就是内存块。
如果一个程序要访问其自身内存块之外的数组,或在数组初始化前使用内存(程序中常见的错误),都会产生难以预料的后果。
Java的主要目标之一是安全性,所以许多在C和C++里困扰程序员的问题在Java里不会再出现。
Java确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下标检查为代价的。
但由此换来的是安全性和效率的提高,因此付出的代价是值得的(并且Java有时可以优化这些操作)。
当创建一个数组对象时.实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null。
一旦Java看到null,就知道这个引用还没有指向某个对象。在使用任何引用前,必须为其指定一个对象;
如果试图使用一个还是null的引用,在运行时将会报错;因此,常犯的数组错误在Java中就可以避免。
还可以创建用来存放基本数据类型的数组。同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部置零。
数组将在以后的章节中详细讨论。
2.3 永远不需要销毁对象
在大多数程序设计语言中,变量生命周期的概念,占据了程序设计工作中非常重要的部分。
变量需要存活多长时间?如果想要销毁对象,那什么时刻进行呢?
变量生命周期的混乱往往会导致大量的程序bug,本节将介绍Java是怎样替我们完成所有的清理工作,从而大大地简化这个问题的。
2.3.1 作用域
大多数过程型语言都有作用域(scope)的概念。作用域决定了在其内定义的变量名的可见性和生命周期。
在C、C++和Java中,作用域由花括号的位置决定。例如:
{
int x = 12;
//Only x available
{
int q = 96;
//Both x & q available
}
//Only x avai1able
//q is out of scope
}
在作用域里定义的变量只可用于作用域结束之前。
任何位于"//"之后到行末的文字都是注释。
缩排格式使Java代码更易干阅读。由于Java是一种自由格式(free-form)的语言,所以,空格、制表符、换行都不会影响程序的执行结果。
尽管以下代码在C和C++中是合法的,但是在Java中却不能这样书写:
{
int x = 12;
{
int x = 96;//Illegal
}
}
编译器将会报告变量x已经定义过。所以,在C和C++里将一个较大作用域的变量“隐藏”起来的做法,在Java里是不允许的。
因为Java设计者认为这样做会导致程序混乱。
2.3.2 对象的作用域
Java对象不具备和基本类型一样的生命周期。当用new创建一个Java对象时,它可以存活于作用域之外。
所以假如你采用代码
{
String s = new String("a string");
}// End of scope
引用s在作用域终点就消失了。然而,s指向的Srting对象仍继续占据内存空间。
在这一小段代码中,我们无法在这个作用域之后访问这个对象,因为对它唯一的引用已超出了作用域的范围。
在后继章节中,读者将会看到:在程序执行过程中,怎样传递和复制对象引用。
事实证明,由new创建的对象,只要你需要,就会一直保留下去。
这样,许多C++编程问题在Java中就完全消失了。
在C++中,你不仅必须要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在你使用完它们之后, 将其销毁。
这样便带来一个有趣的问题。如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?
这正是C++里可能会发生的问题。这也是Java神奇之所在。
Java有一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。
随后,释放这些对象的内存空间,以便供其他新的对象使用。也就是说,你根本不必担心内存回收的问题。
你只需要创建对象,一旦不再需要,它们就会自行消失。
这样做就消除了这类编程问题(即“内存泄漏”),这是由于程序员忘记释放内存而产生的问题。
2.4 创建新的数据类型:类
如果一切都是对象,那么是什么决定了某一类对象的外观与行为呢?换句话说,是什么确定了对象的类型?
你可能期望有一个名为“type”的关键字,当然它必须还要有相应的含义。
然而,从历史发展角度来看,大多数面向对象的程序设计语言习惯用关键字class来表示“我准备告诉你一种新类型的对象看起来像什么样子 ”。
class这个关键字(以后会频繁使用,本书以后就不再用粗体字表示)之后紧跟着的是新类型的名称。
例如;
class ATypeName { /* Class body goes here */ };
这就引入了一种新的类型,尽管类主体仅包含一条注释语句(星号和斜杠以及其中的内容就是注释,本章后面再讨论)。
因此,你还不能用它做太多的事情。然而,你已经可以用new来创建这种类型的对象:
ATypeName a = new ATypeName();
但是,在定义它的所有方法之前,还没有办法能让它去做更多的事情(也就是说,不能向它发送任何有意义的消息)。