一切都是对象---JAVA编程思想
一切都是对象
“如果我们说另一种不同的语言,那么我们就会发觉一个有些不同的世界。”——Luduing Wittgerstein(1889-1951)
尽管Java是基于C++的,但是相比之下,Java是一种更“纯粹”的面向对象设计语言。
Java语言假设我们只进行面向对象的程序设计;而C++不同,因为C++是C的一个超集,所以,C++在某些方面显得过于复杂。
2.1 用引用操纵对象
程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C和C++这里的指针)来操作对象?
这一切在Java里都得到了简化。一切都被视为对象,因此可采用单一固定的语法。尽管一切都看做对象,但操纵的标识符实际上是对象的一个“引用”。形如:String s
中的s就是引用。
2.2 必须由你创建所有对象
一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用new操作符来实现这一目的。形如:String s = new String("");
这种形式。
程序运行时,对象是怎么进行放置安排的呢?特别是内存是怎样分配的呢?
有五种不同的地方可以存储数据:
- 寄存器。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量及其有限,所以寄存器根据需求进行分配。你不能直接控制,也不能再程序中感觉到寄存器存在的任何迹象(C和C++允许你向编译器建议寄存器的分配方式)。
- 堆栈。位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接支持。堆栈指针向下移动,则分配新内存;向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,Java系统必须知道存储在堆栈内所有项的确切生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些Java数据存储在堆栈中——特别是对象引用,但是Java对象并不存储在其中。
- 堆。一种通用的内存池(也位于RAM区),用于存放所有的Java对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多长时间。因此,在堆里分配内存有很大的灵活性。当需要一个对象时,只需用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。当然,为这种灵活性必须要付出相应的代价:用堆进行存储分配和清理可能比用堆栈进行存储分配需要更多时间(如果确实可以在Java中像C++中一样在栈中创建对象,言外之意是说Java没有像C++一样在栈中创建对象的本事。当然,基本类型可以在栈中创建)。
- 常量存储。常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会改变。有时,在嵌入式系统中,常量本身会和其他部分离开,所以在这种情况下,可以选择将其放在ROM(只读存储器)中。
- 非RAM存储。如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中两个基本的例子就是流对象和持久化对象。在流对象中,对象转化成字节流,通常被发送给另一台机器。在持久化对象中,对象被存放在磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。这种存储方式的技巧在于;把对象转化成可以存放在其他媒介上的事物,在需要时,可恢复成常规的、基于RAM的对象。Java提供了对轻量级持久化的支持,而诸如JDBC和Hibernate这样的机制提供了更加复杂的对在数据库中存储和读取对象信息的支持。
以上都在说“引用”对象,我们看一个特例:基本类型
为什么要存在基本类型呢?
因为new将对象存储在“堆”里,用new创建一个小的、简单的变量,往往不是很有效。因此,对于这些类型,Java采用与C和C++相同的方法。也就是说,不用new来创建变量,而是创建一个并非是引用的“自动”变量。这个变量直接存储“值”,并置于堆栈中,因此更加高效。
Java的基本数据类型所占存储空间的大小:
这里指出:Boolean只有true或flase,以及Java SE5的自动包装,还有高精度数字BigInteger和BigDecimal的类型。
BigInteger支持任意精度的整数。
BigDecimal支持任何进度的定点数。
Java中的数组
几乎所有的程序都支持数组。在C和C++中使用数组是危险的,因为C和C++中的数组就是内存块。如果一个程序要访问其自身内存块之外的数组,或在数组初始化前使用内存(程序中常见的错误),都会产生难以预料的后果(改天可以试试,嘿嘿)。
Java的主要目标之一是安全性。Java会确保数组被初始化,并且会检查数组下标是否越界。虽然这种范围检查是以每个数组上少量的内存开销及运行时的下标检查为代价的。但换来的是安全性和效率的提高,因此付出的代价是值得的。
创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动的被初始化为一个特定值null。
2.3 永远不需要销毁对象
大多数程序设计语言中,变量生命周期的概念,占据了程序设计工作中非常重要的部分。
作用域,大多数过程语言都有作用域(scope)的概念。作用域决定了在其内定义的变量名的可见性和生命周期。在C、C++和Java中,作用域由花括号的位置决定。
对象的作用域,Java对象不具备和基本类型一样的生命周期。当用new创建一个Java对象时,它可以存活于作用域之外。如下:
{
String s = new String("");
}
引用s在作用域终点就消失了。然而,s指向的String对象仍继续占据内存空间。
事实证明,由new创建的对象,只要你需要,就会一直保留下去。这样,许多C++编程问题在Java中就完全消失了。在C++中,你不仅必须要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在你使用完它们之后,将其销毁。
不过这样就带来了一个问题。靠什么才能防止这些对象填满内存空间,进而阻塞你的程序呢?没错,就是我们的垃圾回收器,它用来释放那些不会再被引用的对象,将内存空间提供给新的对象使用。
2.4 创建新的数据类型:类
用class这个关键字,有方法和字段。不做阐述!!
注意:局部变量没有默认初始化(也就是方法内的变量),成员变量(也就是字段)有默认初始化。
2.5 方法、参数和返回值
调用方法,通常被称为发送消息给对象。
参数列表和返回值,不做阐述!
2.6 构建一个Java程序
名字可见性,Java采用一种全新的方法来避免类名或者函数名互相冲突。就是增加一个包名(package关键字),一般我们将包名设为我们的域名,如(com.baidu.www,是反着写)(因为域名是唯一的)。
运用其他构件,我需要引入别人的库?那就需要用到import 你需要引入库的包名(例如,import java.util.*)。
static关键字,有些面向对象语言采用类数据和类方法。类数据和类方法是作为整个类存在的,而不是类的某个特定对象存在的(类与对象都直接使用静态成员和静态方法)。
2.9 编码风格
“驼峰风格”,类名的首字母大写;如果类名由几个单词构成,那么把它们连在一起并且每个单词首字母大写。字段名与类名相似,除了第一个单词的首字母不大写以外,其他都单词首字母都大写。
本章完
上一篇: 聊聊高并发系统之HTTP缓存
下一篇: 聊聊高并发系统之HTTP缓存