标签:
一切都是对象
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/51040221
尽管以C++为基础,但 Java 是一种更纯粹的面向对象程序设计语言
正式用它设计之前,必须先将自己的思想转入一个面向对象的世界
在 Java 里,任何东西都可看作对象。可采用一种统一的语法,任何地方均可照搬不误。注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。
创建句柄时,希望同一个新对象连接。通常用 new关键字达到这一目的。
程序运行时,特别要注意的是内存的分配。
有六个地方都可以保存数据
这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。
驻留于常规 RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,Java 编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java 数据要保存在堆栈里——特别是对象句柄,但Java 对象并不放到其中。
一种常规用途的内存池(也在 RAM区域),其中保存了Java 对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!
“静态”(Static)是指“位于固定位置”(也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static 关键字指出一个对象的特定元素是静态的。但 Java 对象本身永远都不会置入静态存储空间。
常数值通常直接置于程序代码内部。它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。
若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。
其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。
有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们。
几乎所有程序设计语言都支持数组。在C和C++里使用数组是非常危险的,因为那些数组只是内存块。若程序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果。在C++里,应尽量不要使用数组,换用标准模板库(Standard TemplateLibrary)里更安全的容器。
Java 的一项主要设计目标就是安全性。所以在C 和C++里困扰程序员的许多问题都未在Java 里重复。一个Java 可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。换回的是更高的安全性,以及更高的工作效率。为此付出少许代价是值得的。
在大多数程序设计语言中,变量的“存在时间”(Lifetime)一直是程序员需要着重考虑的问题。
大多数程序设计语言都提供了“作用域”(Scope)的概念。对于在作用域里定义的名字,作用域同时决定了它的“可见性”以及“存在时间”。
Java 对象不具备与主类型一样的存在时间。用new 关键字创建一个Java 对象的时候,它会超出作用域的范围之外。
在 C++里,一旦工作完成,必须保证将对象清除。
Java 有一个特别的“垃圾收集器”,它会查找用new创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根本不必操心内存的回收问题。只需简单地创建对象,一旦不再需要它们,它们就会自动离去。这样做可防止在C++里很常见的一个编程问题:由于程序员忘记释放内存造成的“内存溢出”。
但从历史看来,大多数面向对象的语言都用关键字“class”表达这样一个意思:“我准备告诉你对象一种新类型的外观”。在这个关键字的后面,应该跟随新数据类型的名称。例如:
class ATypeName{/*类主体置于这里}
这样就引入了一种新类型,接下来便可用new 创建这种类型的一个新对象:
ATypeName a =new ATypeName();
在ATypeName 里,类主体只由一条注释构成(星号和斜杠以及其中的内容,本章后面还会详细讲述),所以并不能对它做太多的事情。事实上,除非为其定义了某些方法,否则根本不能指示它做任何事情。
可在自己的类里设置两种类型的元素:数据成员(有时也叫“字段”)以及成员函数(通常叫“方法”)
数据成员是一种对象(通过它的句柄与其通信),可以为任何类型。它也可以是主类型(并不是句柄)之一。如果是指向对象的一个句柄,则必须初始化那个句柄,用一种名为“构建器”(的特殊函数将其与一个实际对象连接起来(就象使用new关键字)。
但若是一种主类型,则可在类定义位置直接初始化(正如后面会看到的那样,句柄亦可在定义位置初始化)。
每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。
一旦将变量作为类成员使用,就要特别注意由 Java 分配的默认值。这样做可保证主类型的成员变量肯定得到了初始化(C++不具备这一功能),可有效遏止多种相关的编程错误。
JAVA用方法来替代 函数的叫法。
返回类型是指调用方法之后返回的数值类型。显然,方法名的作用是对具体的方法进行标识和引用。自变量列表列出了想传递给方法的信息类型和名称。
Java 的方法只能作为类的一部分创建。只能针对某个对象调用一个方法,而且那个对象必须能够执行那个方法调用。若试图为一个对象调用错误的方法,就会在编译期得到一条出错消息。为一个对象调用方法时,需要先列出对象的名字,在后面跟上一个句点,再跟上方法名以及它的参数列表。即“对象名.方法名(自变量1,自变量2,自变量3...)。
假设我们有一个方法名叫f(),它没有自变量,返回的是类型为int的一个值。那么,假设有一个名为 a 的对象,可为其调用方法f(),则代码如下:
int x = a.f();
返回值的类型必须兼容 x的类型。
象这样调用一个方法的行动通常叫作“向对象发送一条消息”。在上面的例子中,消息是f(),而对象是 a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。在上面的例子中,消息是f(),而对象是 a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。
自变量列表规定了我们传送给方法的是什么信息。采用的都是对象的形式。我们必须在自变量列表里指定要传递的对象类型,以及每个对象的名字。正如在Java 其他地方处理对象时一样,我们实际传递的是“句柄”。倘若希望自变量是一个“字串”,那么传递的必须是一个字串。
一个程序只是一系列对象的集合,它们的方法将其他对象作为自己的自变量使用,而且将消息发给那些对象。
在所有程序设计语言里,一个不可避免的问题是对名字或名称的控制。
如何区分两个名字,并防止两个名字互相冲突呢?C++用额外的关键字引入了“命名空间”的概念。Java为了给一个库生成明确的名字,采用了与Internet域名类似的名字,所以能完全避免这些问题。
一旦要在自己的程序里使用一个预先定义好的类,编译器就必须知道如何找到它。
import的作用是指示编译器导入一个“包”——或者说一个“类库”(Java 的所有代码都必须写入一个类中)。
大多数时候,直接采用来自标准Java 库的组件(部件)即可,它们是与编译器配套提供的。使用这些组件时,没有必要关心冗长的保留域名
除非用new 创建那个类的一个对象,否则实际上并未得到任何东西。只有执行了new 后,才会正式生成数据存储空间,并可使用相应的方法。
在两种特殊的情形下,上述方法并不堪用。一种情形是只想用一个存储区域来保存一个特定的数据——无论要创建多少个对象,甚至根本不创建对象。另一种情形是我们需要一个特殊的方法,它没有与这个类的任何对象关联。也就是说,即使没有创建对象,也需要一个能调用的方法。为满足这两方面的要求,可使用static(静态)关键字。一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起。所以尽管从未创建那个类的一个对象,仍能调用一个 static方法,或访问一些 static数据。
对于非 static数据和方法,我们必须创建一个对象,并用那个对象访问数据或方法。这是由于非static数据和方法必须知道它们操作的具体对象。当然,在正式使用前,由于static方法不需要创建任何对象,所以它们不可简单地调用其他那些成员,同时不引用一个已命名的对象,从而直接访问非 static成员或方法(因为非static成员和方法必须同一个特定的对象关联到一起)。
有些面向对象的语言使用了“类数据”和“类方法”这两个术语。它们意味着数据和方法只是为作为一个整体的类而存在的,并不是为那个类的任何特定对象。
static一项重要的用途就是帮助我们在不必创建对象的前提下调用那个方法。正如以后会看到的那样,这一点是至关重要的——特别是在定义程序运行入口方法main()的时候。
和其他任何方法一样,static方法也能创建自己类型的命名对象。所以经常把static方法作为一个“领头羊”使用,用它生成一系列自己类型的“实例”.
标签:
原文地址:http://blog.csdn.net/notbaron/article/details/51040221