Everything Is an Object
“If we spoke a different language, we would perceive a somewhat different world.” Ludwig Wittgenstein (1889-1951)
Although it is based on C , Java is more of a “pure” object-oriented language.
Both C and Java are hybrid languages, but in Java the designers felt that the hybridization was not as important as it was in C . A hybrid language allows multiple programming styles; the reason C is hybrid is to support backward compatibility with the C language. Because C is a superset of the C language, it includes many of that languagersquo;s undesirable features, which can make some aspects of C overly complicated.
The Java language assumes that you want to do only object-oriented programming. This means that before you can begin you must shift your mindset into an object-oriented world (unless itrsquo;s already there). The benefit of this initial effort is the ability to program in a language that is simpler to learn and to use than many other OOP languages. In this chapter yoursquo;ll see the basic components of a Java program and learn that (almost) everything in Java is an object.
You manipulate objects with references
Each programming language has its own means of manipulating elements in memory. Sometimes the programmer must be constantly aware of what type of manipulation is going on. Are you manipulating the element directly, or are you dealing with some kind of indirect representation (a pointer in C or C ) that must be treated with a special syntax?
All this is simplified in Java. You treat everything as an object, using a single consistent syntax. Although you treat everything as an object, the identifier you manipulate is actually a “reference” to an object.1 You might imagine a television (the object) and a remote control (the reference). As long as yoursquo;re holding this reference, you have a connection to the television, but when someone says, “Change the channel” or “Lower the volume,” what yoursquo;re manipulating is the reference, which in turn modifies the object. If you want to move around
1 This can be a flashpoint. There are those who say, “Clearly, itrsquo;s a pointer,” but this presumes an underlying implementation. Also, Java references are much more akin to C references than to pointers in their syntax. In the 1st edition of this book, I chose to invent a new term, “handle,” because C references and Java references have some important differences. I was coming out of C and did not want to confuse the C programmers whom I assumed would be the largest audience for Java. In the 2nd edition, I decided that “reference” was the more commonly used term, and that anyone changing from C would have a lot more to cope with than the terminology of references, so they might as well jump in with both feet. However, there are people who disagree even with the term “reference.” I read in one book where it was “completely wrong to say that Java supports pass by reference,” because Java object identifiers (according to that author) are actually “object references.” And (he goes on) everything is actually pass by value. So yoursquo;re not passing by reference, yoursquo;re “passing an object reference by value.” One could argue for the precision of such convoluted explanations, but I think my approach simplifies the understanding of the concept without hurting anything (well, the language lawyers may claim that Irsquo;m lying to you, but Irsquo;ll say that Irsquo;m providing an appropriate abstraction). the room and still control the television, you take the remote/reference with you, not the television.
Also, the remote control can stand on its own, with no television. That is, just because you have a reference doesnrsquo;t mean therersquo;s necessarily an object connected to it. So if you want to hold a word or sentence, you create a String reference:
String s;
But here yoursquo;ve created only the reference, not an object. If you decided to send a message to s at this point, yoursquo;ll get an error because s isnrsquo;t actually attached to anything (therersquo;s no television). A safer practice, then, is always to initialize a reference when you create it:
String s = 'asdf';
However, this uses a special Java feature: Strings can be initialized with quoted text. Normally, you must use a more general type of initialization for objects.
You must createall the objects
When you create a reference, you want to connect it with a new object. You do so, in general, with the new operator. The keyword new says, “Make me a new one of these objects.” So in the preceding example, you can say:
String s = new String('asdf');
Not only does this mean “Make me a new String,” but it also gives information about how to make the String by supplying an initial character string.
Of course, Java comes with a plethora of ready-made types in addition to String. Whatrsquo;s more important is that you can create your own types. In fact, creating new types is the fundamental activity in Java programming, and itrsquo;s what yoursquo;ll be learning about in the rest of this book.
Where storage lives
Itrsquo;s useful to visualize some aspects of how things are laid out while the program is running— in particular how memory is arranged. There are five different places to store data:
1. Registers. This is the fastest storage because it exists in a place different from that of other storage: inside the processor. However, the number of registers is severely limited, so registers are allocated as they are needed. You donrsquo;t have direct control, nor do you see any evidence in your programs that registers even exist (C amp; C , on the
剩余内容已隐藏,支付完成后下载完整资料
一切都是对象
“如果我们说一种不同的语言,我们将看到一个不同的世界”路德维希·维特根斯坦(1889-1951)
“尽管以C 为基础,但 Java 是一种更纯粹的面向对象程序设计语言”。 无论C 还是Java 都属于杂合语言。但在 Java 中,设计者觉得这种杂合并不象在 C 里那么重要。杂合语言 允许采用多种编程风格;之所以说 C 是一种杂合语言,是因为它支持与 C语言的向后兼容能力。由于C 是 C的一个超集,所以包含的许多特性都是后者不具备的,这些特性使 C 在某些地方显得过于复杂。 Java 语言首先便假定了我们只希望进行面向对象的程序设计。也就是说,正式用它设计之前,必须先将自己 的思想转入一个面向对象的世界(除非早已习惯了这个世界的思维方式)。只有做好这个准备工作,与其他 OOP语言相比,才能体会到 Java 的易学易用。在本章,我们将探讨 Java 程序的基本组件,并体会为什么说 Java 乃至Java 程序内的一切都是对象。
用句柄操纵对象
每种编程语言都有自己的数据处理方式。有些时候,程序员必须时刻留意准备处理的是什么类型。您曾利用 一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C 或C 里的指针)? 所有这些在 Java 里都得到了简化,任何东西都可看作对象。因此,我们可采用一种统一的语法,任何地方均 可照搬不误。但要注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄” (Handle)。在其他 Java 参考书里,还可看到有的人将其称作一个“引用”,甚至一个“指针”。可将这一 情形想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的 通道。但一旦需要“换频道”或者“关小声音”,我们实际操纵的是遥控板(句柄),再由遥控板自己操纵 电视机(对象)。如果要在房间里四处走走,并想保持对电视机的控制,那么手上拿着的是遥控板,而非电 视机。 此外,即使没有电视机,遥控板亦可独立存在。也就是说,只是由于拥有一个句柄,并不表示必须有一个对 象同它连接。所以如果想容纳一个词或句子,可创建一个 String句柄: String s; 但这里创建的只是句柄,并不是对象。若此时向s 发送一条消息,就会获得一个错误(运行期)。这是由于 s实际并未与任何东西连接(即“没有电视机”)。因此,一种更安全的做法是:创建一个句柄时,记住无 论如何都进行初始化: String s = 'asdf'; 然而,这里采用的是一种特殊类型:字串可用加引号的文字初始化。通常,必须为对象使用一种更通用的初 始化类型。
所有对象都必须创建
创建句柄时,我们希望它同一个新对象连接。通常用new 关键字达到这一目的。new的意思是:“把我变成 这些对象的一种新类型”。所以在上面的例子中,可以说: String s = new String('asdf'); 它不仅指出“将我变成一个新字串”,也通过提供一个初始字串,指出了“如何生成这个新字串”。 当然,字串(String)并非唯一的类型。Java 配套提供了数量众多的现成类型。对我们来讲,最重要的就是 记住能自行创建类型。事实上,这应是Java 程序设计的一项基本操作,是继续本书后余部分学习的基础。
保存到什么地方
程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的是内存的分配。有六个地方都可 以保存数据:
- 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存 器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的 程序里找到寄存器存在的任何踪迹。
(2) 堆栈。驻留于常规 RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆 栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存 方式,仅次于寄存器。创建程序时,Java 编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存 在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活 性,所以尽管有些 Java 数据要保存在堆栈里——特别是对象句柄,但Java 对象并不放到其中。
(3) 堆。一种常规用途的内存池(也在 RAM区域),其中保存了Java 对象。和堆栈不同,“内存堆”或 “堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要 在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命 令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然 会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!
(4) 静态存储。这儿的“静态”(Static)是指“位于固定位置”(尽管也在 RAM里)。程序运行期间,静 态存储的数据将随时等候调用。可用static 关键字指出一个对象的特定元素是静态的。但 Java 对象本身永 远都不会置入静态存储空间。
(5) 常数存储。常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数 需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。
(6) 非RAM 存储。若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。 其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给 另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对 于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复 成普通的、基于RAM的对象。Java 1.1 提供了对Lightweight persistence 的支持。未来的版本甚至可能提 供更完整的方案。
特殊情况:主要类型
有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计 时要频繁用到它们。之所以要特别对待,是由于用 new创建对象(特别是小的、简单的变量)并不是非常有 效,因为new将对象置于“堆”里。对于这些类型,Java 采纳了与 C和 C 相同的方法。也就是说,不是用 new创建变量,而是创建一个并非句柄的“自动”变量。这个变量容纳了具体的值,并置于堆栈中,能够更 高效地存取。 Java 决定了每种主要类型的大小。就象在大多数语言里那样,这些大小并不随着机器结构的变化而变化。这 种大小的不可更改正是 Java 程序具有很强移植能力的原因之一。
数值类型全都是有符号(正负号)的,所以不必费劲寻找没有符号的类型。 主数据类型也拥有自己的“封装器”(wrapper)类。这意味着假如想让堆内一个非主要对象表示那个主类 型,就要使用对应的封装器。例如: char c = x; Character C = new Character(c); 也可以直接使用: Character C = new Character(x); 这样做的原因将在以后的章节里解释。
高精度数字
Java 1.1 增加了两个类,用于进行高精度的计算:BigInteger和 BigDecimal。尽管它们大致可以划分为 “封装器”类型,但两者都没有对应的“主类型”。
这两个类都有自己特殊的“方法”,对应于我们针对主类型执行的操作。也就是说,能对int或 float做的 事情,对BigInteger 和BigDecimal 一样可以做。只是必须使用方法调用,不能使用运算符。此外,由于牵 涉更多,所以运算速度会慢一些。我们牺牲了速度,但换来了精度。 BigInteger支持任意精度的整数。也就是说,我们可精确表示任意大小的整数值,同时在运算过程中不会丢 失任何信息。 BigDecimal支持任意精度的定点数字。例如,可用它进行精确的币值计算。 至于调用这两个类时可选用的构建器和方法,请自行参考联机帮助文档。
Java 的数组
几乎所有程序设计语言都支持数组。在C和 C 里使用数组是非常危险的,因为那些数组只是内存块。若程 序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果 。
Java 的一项主要设计目标就是安全性。所以在 C 和 C 里困扰程序员的许多问题都未在Java 里重复。一个 Java 可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些 代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。但由此换回的是更高的安 全性,以及更高的工作效率。为此付出少许代价是值得的。 创建对象数组时,实际创建的是一个句柄数组。而且每个句柄都会自动初始化成一个特殊值,并带有自己的 关键字:null(空)。一旦 Java 看到null,就知道该句柄并未指向一个对象。正式使用前,必须为每个句 柄都分配一个对象。若试图使用依然为null 的一个句柄,就会在运行期报告问题。因此,典型的数组错误在 Java 里就得到了避免。 也可以创建主类型数组。同样地,编译器能够担保对它的初始化,因为会将那个数组的内存划分成零。 数组问题将在以后的章节里详细讨论。
绝对不要清除对象
在大多数程序设计语言中,变量的“存在时间”(Lifetime)一直是程序员需要着重考虑的问题。变量应持 续多长的时间?如果想清除它,那么何时进行?在变量存在时间上纠缠不清会造成大量的程序错误。在下面 的小节里,将阐示 Java 如何帮助我们完成所有清除工作,从而极大了简化了这个问题。
作用域
大多数程序设计语言都提供了“作用域”(Scope)的概念。对于在作用域里定义的名字,作用域同时决定了 它的“可见性”以及“存在时间”。在C,C 和 Java 里,作用域是由花括号的位置决定的。参考下面这个 例子:
{ int x = 12; /* only x available */
{ int q = 96; /* both x amp; q available */
}
/* only x available */ /* q “out of scope” */ }
作为在作用域里定义的一个变量,它只有在那个作用域结束之前才可使用。 在上面的例子中,缩进排版使 Java 代码更易辨读。由于 Java 是一种形式自由的语言,所以额外的空格、制 表位以及回车都不会对结果程序造成影响。 注意尽管在 C和 C 里是合法的,但在 Java 里不能象下面这样书写代码:
{ int x = 12;
{ int x = 96; /* illegal */
}
}
编译器会认为变量 x 已被定义。所以C 和C 能将一个变量“隐藏”在一个更大的作用域里。但这种做法在 Java 里是不允许的,因为Java 的设计者认为这样做使程序产生了混淆。
对象的作用域
Java 对象不具备与主类型一样的存在时间。用 new 关键字创建一个Java 对象的时候,它会超出作用域的范 围之外。所以假若使用下面这段代码:
{ String s = new String('a string'); } /* 作用域的终点 */
那么句柄s 会在作用域的终点处消失。然而,s指向的 String 对象依然占据着内存空间。在上面这段代码 里,我们没有办法访问对象,因为指向它的唯一一个句柄已超出了作用域的边界。在后面的章节里,大家还 会继续学习如何在程序运行期间传递和复制对象句柄。 这样造成的结果便是:对于用 new 创建的对象,只要我们愿意,它们就会一直保留下去。这个编程问题在C 和C 里特别突出。看来在C 里遇到的麻烦最大:由于不能从语言获得任何帮助,所以在需要对象的时候, 根本无法确定它们是否可用。而且更麻烦的是,在 C 里,一旦工作完成,必须保证将对象清除。 这样便带来了一个有趣的问题。假如Java 让对象依然故我,怎样才能防止它们大量充斥内存,并最终造成程 序的“凝固”呢。在C 里,这个问题最令程序员头痛。但 Java 以后,情况却发生了改观。Java 有一个特别 的“垃圾收集器”,它会查找用new创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由 那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根本不必操心内存的回收问题。只需简单地 创建对象,一旦不再需要它们,它们就会自动离去。这样做可防止在 C 里很常见的一个编程问题:由于程 序员忘记释放内存造成的“内存溢出”。
新建数据类型:类
如果说一切东西都是对象,那么用什么决定一个“类”(Class)的外观与行为呢?换句话说,是什么建立起 了一个对象的“类型”(Type)呢?大家可能猜想有一个名为“type”的关键字。但从历史看来,大多数面 向对象的语言都用关键字“class”表达这样一个意思:“我准备告诉你对象一种新类型的外观”。class 关 键字太常用了,以至于本书许多地方并没有用粗体字或双引号加以强调。在这个关键字的后面,应该跟随新 数据类型的名称。例如: class ATypeName {/*类主体置于这里} 这样就引入了一种新类型,接下来便可用 new 创建这种类型的一个新对象: ATypeName a = new ATypeName
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[147024],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。