java编程思想--2一切都是对象

一切都是对象
尽管以C++为基础,但 Java 是一种更纯粹的面向对象程序设计语言
正式用它设计之前,必须先将自己的思想转入一个面向对象的世界
1 用句柄操纵对象

在 Java 里,任何东西都可看作对象。可采用一种统一的语法,任何地方均可照搬不误。注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。
2 所有对象都必须创建

创建句柄时,希望同一个新对象连接。通常用 new关键字达到这一目的。
程序运行时,特别要注意的是内存的分配。
有六个地方都可以保存数据
2.1 寄存器

这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。
2.2 堆栈

驻留于常规 RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,Java 编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java 数据要保存在堆栈里——特别是对象句柄,但Java 对象并不放到其中。
2.3 堆

一种常规用途的内存池(也在 RAM区域),其中保存了Java 对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!
2.4 静态存储

“静态”(Static)是指“位于固定位置”(也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static 关键字指出一个对象的特定元素是静态的。但 Java 对象本身永远都不会置入静态存储空间。
2.5 常数存储

常数值通常直接置于程序代码内部。它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。
2.6 非RAM 存储

若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。
其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。
2.6.1 主要类型

有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们。
2.6.2 Java 的数组

几乎所有程序设计语言都支持数组。在C和C++里使用数组是非常危险的,因为那些数组只是内存块。若程序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果。在C++里,应尽量不要使用数组,换用标准模板库(Standard TemplateLibrary)里更安全的容器。
Java 的一项主要设计目标就是安全性。所以在C 和C++里困扰程序员的许多问题都未在Java 里重复。一个Java 可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。换回的是更高的安全性,以及更高的工作效率。为此付出少许代价是值得的。
2.7 不要清除对象

在大多数程序设计语言中,变量的“存在时间”(Lifetime)一直是程序员需要着重考虑的问题。
大多数程序设计语言都提供了“作用域”(Scope)的概念。对于在作用域里定义的名字,作用域同时决定了它的“可见性”以及“存在时间”。
Java 对象不具备与主类型一样的存在时间。用new 关键字创建一个Java 对象的时候,它会超出作用域的范围之外。
在 C++里,一旦工作完成,必须保证将对象清除。
Java 有一个特别的“垃圾收集器”,它会查找用new创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根本不必操心内存的回收问题。只需简单地创建对象,一旦不再需要它们,它们就会自动离去。这样做可防止在C++里很常见的一个编程问题:由于程序员忘记释放内存造成的“内存溢出”。
2.8 数据类型:类

但从历史看来,大多数面向对象的语言都用关键字“class”表达这样一个意思:“我准备告诉你对象一种新类型的外观”。在这个关键字的后面,应该跟随新数据类型的名称。例如:
class ATypeName{/*类主体置于这里}
这样就引入了一种新类型,接下来便可用new 创建这种类型的一个新对象:
ATypeName a =new ATypeName();
在ATypeName 里,类主体只由一条注释构成(星号和斜杠以及其中的内容,本章后面还会详细讲述),所以并不能对它做太多的事情。事实上,除非为其定义了某些方法,否则根本不能指示它做任何事情。
2.8.1 字段和方法

可在自己的类里设置两种类型的元素:数据成员(有时也叫“字段”)以及成员函数(通常叫“方法”)
数据成员是一种对象(通过它的句柄与其通信),可以为任何类型。它也可以是主类型(并不是句柄)之一。如果是指向对象的一个句柄,则必须初始化那个句柄,用一种名为“构建器”(的特殊函数将其与一个实际对象连接起来(就象使用new关键字)。
但若是一种主类型,则可在类定义位置直接初始化(正如后面会看到的那样,句柄亦可在定义位置初始化)。
每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。
一旦将变量作为类成员使用,就要特别注意由 Java 分配的默认值。这样做可保证主类型的成员变量肯定得到了初始化(C++不具备这一功能),可有效遏止多种相关的编程错误。
2.9 方法、自变量和返回值

JAVA用方法来替代 函数的叫法。
返回类型是指调用方法之后返回的数值类型。显然,方法名的作用是对具体的方法进行标识和引用。自变量列表列出了想传递给方法的信息类型和名称。
Java 的方法只能作为类的一部分创建。只能针对某个对象调用一个方法,而且那个对象必须能够执行那个方法调用。若试图为一个对象调用错误的方法,就会在编译期得到一条出错消息。为一个对象调用方法时,需要先列出对象的名字,在后面跟上一个句点,再跟上方法名以及它的参数列表。即“对象名.方法名(自变量1,自变量2,自变量3...)。
假设我们有一个方法名叫f(),它没有自变量,返回的是类型为int的一个值。那么,假设有一个名为 a 的对象,可为其调用方法f(),则代码如下:
int x = a.f();
返回值的类型必须兼容 x的类型。
象这样调用一个方法的行动通常叫作“向对象发送一条消息”。在上面的例子中,消息是f(),而对象是 a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。在上面的例子中,消息是f(),而对象是 a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。
2.9.1 自变量列表

自变量列表规定了我们传送给方法的是什么信息。采用的都是对象的形式。我们必须在自变量列表里指定要传递的对象类型,以及每个对象的名字。正如在Java 其他地方处理对象时一样,我们实际传递的是“句柄”。倘若希望自变量是一个“字串”,那么传递的必须是一个字串。
一个程序只是一系列对象的集合,它们的方法将其他对象作为自己的自变量使用,而且将消息发给那些对象。
2.10 构建JAVA程序

2.10.1 名字可见

在所有程序设计语言里,一个不可避免的问题是对名字或名称的控制。
如何区分两个名字,并防止两个名字互相冲突呢?C++用额外的关键字引入了“命名空间”的概念。Java为了给一个库生成明确的名字,采用了与Internet域名类似的名字,所以能完全避免这些问题。
2.10.2 使用其他组件

一旦要在自己的程序里使用一个预先定义好的类,编译器就必须知道如何找到它。
import的作用是指示编译器导入一个“包”——或者说一个“类库”(Java 的所有代码都必须写入一个类中)。
大多数时候,直接采用来自标准Java 库的组件(部件)即可,它们是与编译器配套提供的。使用这些组件时,没有必要关心冗长的保留域名
2.10.3 static 关键字

除非用new 创建那个类的一个对象,否则实际上并未得到任何东西。只有执行了new 后,才会正式生成数据存储空间,并可使用相应的方法。
在两种特殊的情形下,上述方法并不堪用。一种情形是只想用一个存储区域来保存一个特定的数据——无论要创建多少个对象,甚至根本不创建对象。另一种情形是我们需要一个特殊的方法,它没有与这个类的任何对象关联。也就是说,即使没有创建对象,也需要一个能调用的方法。为满足这两方面的要求,可使用static(静态)关键字。一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起。所以尽管从未创建那个类的一个对象,仍能调用一个 static方法,或访问一些 static数据。
对于非 static数据和方法,我们必须创建一个对象,并用那个对象访问数据或方法。这是由于非static数据和方法必须知道它们操作的具体对象。当然,在正式使用前,由于static方法不需要创建任何对象,所以它们不可简单地调用其他那些成员,同时不引用一个已命名的对象,从而直接访问非 static成员或方法(因为非static成员和方法必须同一个特定的对象关联到一起)。
有些面向对象的语言使用了“类数据”和“类方法”这两个术语。它们意味着数据和方法只是为作为一个整体的类而存在的,并不是为那个类的任何特定对象。
static一项重要的用途就是帮助我们在不必创建对象的前提下调用那个方法。正如以后会看到的那样,这一点是至关重要的——特别是在定义程序运行入口方法main()的时候。
和其他任何方法一样,static方法也能创建自己类型的命名对象。所以经常把static方法作为一个“领头羊”使用,用它生成一系列自己类型的“实例”.

一切都是对象。
我的一位朋友以前的签名是,我一直都在面向对象,可是现在连一个对象都没有。

(一)类引用

假如有一个类  电视机类 class TV;
class TV{
  int length;  //字段,也叫数据成员
  int point(){  //方法,也叫成员函数
    return 1;
  }
}

TV control , control是一个引用(reference),其实重新看C之后发现这引用就跟指针一样,少了个星号而已。
对象的创建用new。
TV Ccontrol = new TV();

同时,我在看数据结构书时候,注意到了初始化的问题。
TV Control;
此时的Control是对象的一个引用,不是对象本身,但是在赋值成某对象,即上面的初始化之前,其实是保存为null的特殊对象的引用。这也回答了,为什么你每次使用对象的时候,IDE会提示对象的未初始化。


(二)内存分配

这东西放哪里呢,那还是要像C一样看内存分配。
1) 寄存器 。 最快的存储区,处理器内部,根据需求分配,不能自己控制,但是C/C++可以用register。

2)栈(原文堆栈,其实应该翻译成栈更合适,和堆区分开来,因为英文的stack就是堆栈的意思)。 位于通用RAM(Random Access Machine,随机访问存储区,在操作系统,微机原理等计算机的基本组成中都有提到),速度仅次于寄存器。存放基本变量和引用,存在栈中的数据可以共享。但是,栈中的数据大小和生存周期必须确定,这是缺点。

栈存的一个是基本的数据类型,int i = 1; 其实i是一个指向int类型的引用。1存在栈中,i指向1的地址(作用和指针一个样),如果此时有int j = 1; 由于共享性,就不会再开辟
一个新的1的地址。直接让i和j指向同一个地址。

栈也存储对象的引用。

3)堆。存放所有的java对象。

4)常量存储。常量(注意常量和变量,int i =1是变量),字符串,静态区的东西存储在此。

5)非RAM存储。

再来看看一个有趣的对象equals和==问题。
TV Control;
//与C++不同的是,C++实际上创建了这个对象,留出了所需要的空间,而java只是创建某一个对象的存储地址的空间。
Control = new TV();
TV AnotherControl = Control;
//C++将所有的数据拷贝到Another中,而java只是把地址复制过去。
//所以两者是否==(java中实际上判断引用是否一致,即对象是否相同),既然地址一致,同一个对象,答案为ture。c++却用==来判断对象的数据是否相同,而java用的是equals,一般重写。

(三)作用域问题
{}作用域里决定了变量的声明周期,变量用于作用域之前,所以有时会犯一些低级错误,在作用域之外又再次使用该变量。就会出现can not be resolved,无法解析的问题了。


(四)第一个HelloWorld程序
程序的开头,要用import语句引入程序所需要的类,java.lang是默认导入进每个java文件的,之前一直奇怪lang是什么——language。

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
其实java也没有那么强大,看,简简单单的HelloWorld要写这么一堆不相关的东西。所以,还是根据需要选择你使用的语言。

(五)编码风格
类名用驼峰标识,首字母大写。几个单词的话就每个单词的首字母大写。
另外加上上次在Google看到的编程风格,
if else while 等语句的使用时,即使是空语句,也要加上{},更容易看。

2.1用引用操作对象
对象访问在Java语言中无处不在,是最普通的程序行为,但即使是最简单的访问,也会却涉及Java栈、Java堆、方法区这三个最重要内存区域之间的关联关系,如下面的这句代码: Object obj = new Object(); 假设这句代码出现在方法体中,那“Object obj”这部分的语义将会反映到Java栈的本地变量表中,作为一个reference类型数据出现。而“new Object()”这部分的语义将会反映到Java堆中,形成一块存储了Object类型所有实例数据值(Instance Data,对象中各个实例字段的数据)的结构化内存,根据具体类型以及虚拟机实现的对象内存布局(Object Memory Layout)的不同,这块内存的长度是不固定的。另外,在Java堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存储在方法区中。
X
由于reference类型在Java虚拟机规范里面只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java堆中的对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同,主流的访问方式有两种:使用句柄和直接指针。
如果使用句柄访问方式,Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息,如图2-2所示。
 
如果使用直接指针访问方式,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址,如图2-3所示。



这两种对象的访问方式各有优势,使用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。
使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销,由于对象的访问在Java中非常频繁,因此这类开销积少成多后也是一项非常可观的执行成本。就本书讨论的主要虚拟机Sun HotSpot而言,它是使用第二种方式进行对象访问的,但从整个软件开发的范围来看,各种语言和框架使用句柄来访问的情况也十分常见。
2.2必须由你创建对象
java基本类型所占基础空间的大小是固定不变的。所有数值类型都有正负号,基本类型包括:boolean,short,int,char,float,double,long,byte.
2.3永远不要销毁对象(可以拓展变量初始化问题)
变量的生命周期。作用域(scope)决定了其内的变量名的可见性和生命周期。在C和C++里将较大作用域的变量隐藏起来的做法,在java中不允许。

2.4创建新的数据类型
若类的成员变量是基本类型,即使没有初始化,java也会确保它获取一个默认值。但是不适应局部变量,所在在使用局部变量时,应先对其赋值否则编译器会报错。
2.5方法、参数、返回值
方法的基本组成部分:名称、参数、返回值和方法体。方法名和参数列表能唯一标识出一个方法。
2.6构建一个java程序
static关键字满足下面两种需求:1.当一个事物是static时,意味着这个域或方法不会与包含他的那个类的任何对象实例关联在一起,所以不用创建对象就可以调用static方法或属性;2.只想为特定域分配单一空间。
2.7你的第一个java程序
2.8注释和嵌入式文档
javadoc是用于提取注释的工具,有两种方式:嵌入HTML或者文档标签。
2.9编码风格
驼峰式命名规则

“尽管以C++为基础,但Java是一种更纯粹的面向对象程序设计语言”。
无论C++还是Java都属于杂合语言。但在Java中,设计者觉得这种杂合并不象在C++里那么重要。杂合语言允许采用多种编程风格;之所以说C++是一种杂合语言,是因为它支持与C语言的向后兼容能力。由于C++是C的一个超集,所以包含的许多特性都是后者不具备的,这些特性使C++在某些地方显得过于复杂。
Java语言首先便假定了我们只希望进行面向对象的程序设计。也就是说,正式用它设计之前,必须先将自己的思想转入一个面向对象的世界(除非早已习惯了这个世界的思维方式)。只有做好这个准备工作,与其他OOP语言相比,才能体会到Java的易学易用。在本章,我们将探讨Java程序的基本组件,并体会为什么说Java乃至Java程序内的一切都是对象。
2.1 用句柄操纵对象
每种编程语言都有自己的数据处理方式。有些时候,程序员必须时刻留意准备处理的是什么类型。您曾利用一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C或C++里的指针)?
所有这些在Java里都得到了简化,任何东西都可看作对象。因此,我们可采用一种统一的语法,任何地方均可照搬不误。但要注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。在其他Java参考书里,还可看到有的人将其称作一个“引用”,甚至一个“指针”。可将这一情形想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。但一旦需要“换频道”或者“关小声音”,我们实际操纵的是遥控板(句柄),再由遥控板自己操纵电视机(对象)。如果要在房间里四处走走,并想保持对电视机的控制,那么手上拿着的是遥控板,而非电视机。
此外,即使没有电视机,遥控板亦可独立存在。也就是说,只是由于拥有一个句柄,并不表示必须有一个对象同它连接。所以如果想容纳一个词或句子,可创建一个String句柄:
Strings;
但这里创建的只是句柄,并不是对象。若此时向s发送一条消息,就会获得一个错误(运行期)。这是由于s实际并未与任何东西连接(即“没有电视机”)。因此,一种更安全的做法是:创建一个句柄时,记住无论如何都进行初始化:
Strings = "asdf";
然而,这里采用的是一种特殊类型:字串可用加引号的文字初始化。通常,必须为对象使用一种更通用的初始化类型。
2.2 所有对象都必须创建
创建句柄时,我们希望它同一个新对象连接。通常用new关键字达到这一目的。new的意思是:“把我变成这些对象的一种新类型”。所以在上面的例子中,可以说:
Strings = newString("asdf");
它不仅指出“将我变成一个新字串”,也通过提供一个初始字串,指出了“如何生成这个新字串”。
当然,字串(String)并非唯一的类型。Java配套提供了数量众多的现成类型。对我们来讲,最重要的就是记住能自行创建类型。事实上,这应是Java程序设计的一项基本操作,是继续本书后余部分学习的基础。
2.2.1 保存到什么地方
程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的是内存的分配。有六个地方都可以保存数据:
(1) 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。
(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的支持。未来的版本甚至可能提供更完整的方案。
2.2.2 特殊情况:主要类型
有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们。之所以要特别对待,是由于用new创建对象(特别是小的、简单的变量)并不是非常有效,因为new将对象置于“堆”里。对于这些类型,Java采纳了与C和C++相同的方法。也就是说,不是用new创建变量,而是创建一个并非句柄的“自动”变量。这个变量容纳了具体的值,并置于堆栈中,能够更高效地存取。
Java决定了每种主要类型的大小。就象在大多数语言里那样,这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。
主类型大小最小值最大值封装器类型
boolean1-bit––Boolean
char16-bitUnicode 0Unicode 216- 1Character
byte8-bit-128+127Byte[11]
short16-bit-215+215– 1Short1
int32-bit-231+231– 1Integer
long64-bit-263+263– 1Long
float32-bitIEEE754IEEE754Float
double64-bitIEEE754IEEE754Double
void–––Void1
①:到Java 1.1才有,1.0版没有。
数值类型全都是有符号(正负号)的,所以不必费劲寻找没有符号的类型。
主数据类型也拥有自己的“封装器”(wrapper)类。这意味着假如想让堆内一个非主要对象表示那个主类型,就要使用对应的封装器。例如:
charc = 'x'; Character C = newCharacter('c');
也可以直接使用:
Character C = newCharacter('x');
这样做的原因将在以后的章节里解释。
1. 高精度数字
Java 1.1增加了两个类,用于进行高精度的计算:BigInteger和BigDecimal。尽管它们大致可以划分为“封装器”类型,但两者都没有对应的“主类型”。
这两个类都有自己特殊的“方法”,对应于我们针对主类型执行的操作。也就是说,能对int或float做的事情,对BigInteger和BigDecimal一样可以做。只是必须使用方法调用,不能使用运算符。此外,由于牵涉更多,所以运算速度会慢一些。我们牺牲了速度,但换来了精度。
BigInteger支持任意精度的整数。也就是说,我们可精确表示任意大小的整数值,同时在运算过程中不会丢失任何信息。
BigDecimal支持任意精度的定点数字。例如,可用它进行精确的币值计算。
至于调用这两个类时可选用的构建器和方法,请自行参考联机帮助文档。
2.2.3 Java的数组
几乎所有程序设计语言都支持数组。在C和C++里使用数组是非常危险的,因为那些数组只是内存块。若程序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果(注释②)。
②:在C++里,应尽量不要使用数组,换用标准模板库(Standard TemplateLibrary)里更安全的容器。
Java的一项主要设计目标就是安全性。所以在C和C++里困扰程序员的许多问题都未在Java里重复。一个Java可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。但由此换回的是更高的安全性,以及更高的工作效率。为此付出少许代价是值得的。
创建对象数组时,实际创建的是一个句柄数组。而且每个句柄都会自动初始化成一个特殊值,并带有自己的关键字:null(空)。一旦Java看到null,就知道该句柄并未指向一个对象。正式使用前,必须为每个句柄都分配一个对象。若试图使用依然为null的一个句柄,就会在运行期报告问题。因此,典型的数组错误在Java里就得到了避免。
也可以创建主类型数组。同样地,编译器能够担保对它的初始化,因为会将那个数组的内存划分成零。
数组问题将在以后的章节里详细讨论。


、java程序运行时对象的存储位置安排:
1、寄存器
这是最快的存储区,在cpu内部,不能直接控制
2、堆栈
位于通用RAM(随机访问存储器),通过堆栈指针可以从处理器获得直接支持,指针向下移动,分配新内存,向上,释放内存。某些java数据存储在堆栈中——对象引用,但java对象不存储于其中,基本类型变量也存储于其中。
3、堆
一种通用的内存池(也位于RAM区),用于存放所有的java对象。不同于堆栈的是编译器不需要存储的数据在堆里存活多长时间。
4、常量存储
常量值通常放在程序代码内部,永远不会被改变。也放在ROM(只读存储器)中
5、非RAM存储
存活于程序之外,程序没有运行时也可以存在,基本例子是流对象和持久化对象。流对象中对象转化为了字节流,发送给另一台机器,持久化对象中对象被存储于磁盘上。
补充:内存一般采用半导体存储单元,包括随机访问存储器(RAM),只读存储器(ROM),以及高速缓存(CACHE)。我们通常所说的内存条指的就是RAM
二、基本数据类型默认值
boolean false _
char null 2
byte (byte)0 1
short (short)0 2
int 0 4
long 0L 8
float 0.0f 4
double 0.0 8
类成员变量不用初始化,java自动赋予默认值
方法中的局部变量一定要初始化,不然编译会出错
三、方法
方法名和参数列表唯一的标识出一个方法。
四、注释
1 //单行
2
3注释文档 javadoc
类注释,字段,方法注释都位于他们的前面,javadoc只能为public和protected成员进行文档注释,private和默认的会被忽略掉。但可以用“-private”进行标记,从而把private成员也包括进来。输出格式是HTML格式。

1.java不同于C,C++,纯粹的面向对象。通过“引用”操作对象。

2.java的存储:1)寄存器2)堆栈(stack),java的对象引用存储于其中,java对象并不存储于其中,3)堆(heap):通用的内存池,存放所有的java对象。4)静态存储:是指存放在固定的位置5)常量存储:存放在程序代码内部,永远不会改变,而嵌入式系统中,常量跟代码是分开的,存放于ROM。6)非RAM存储:典型的例子,流对象和持久化对象

3.基本类型:存放于堆栈中,类型所占用的存储空间已经被确定,是Java具有可移植性的原因之一。

4.高精度数字:BigInteger和BigDecimal,它们没有对应的基本类型。

5.数组(Array):编译器会进行数组的初始化。对象数组的初值为Null,基本数据类型的数组初值为0.

6.永远不需要销毁对象:

作用域:基本类型的作用域由“{”来决定,而对象的作用域可以存活于作用域之外,编译器通过垃圾回收器来管理。

7.基本成员默认值:类成员变量,java给其默认值,而作为“局部变量”(某个方法中的变量)时,若进行编译的话(指这里的变量被调用时),必须进行初始化,不然会报错。

8.java的方法:方法调用—向对象发送消息。

9.static关键字:“类数据”和“类方法”

10.jdk下载:java.sun.com

11.java编程思想的源代码:http://www.bruceeckel.com/

12.ant官方下载地址:http://jakarta.apache.org/ant

13.javadoc:通过doclets的Javadoc处理器来实现,提取注释工具。

14.用于生成javadoc的标签:@see,@link package.class#member label,@docRoot,@inheritDoc,@version,@author,@since,@param,@return,@throws,@deprecated

15.代码风格:驼峰风格,类的首字母大写;如果几个单词在一起,则并在一起,不用下划线隔开。

1、用于操纵的对象标识符实际上只是对象的一个引用(reference),引用指向对象,与对象相关联
2、如“String s;”这样的定义,只创建了一个引用,并没有关联到具体对象,此时向s发送消息(即使用s来调用方法),将会返回运行时错误
3、new关键字,为对象分配存储空间,将对象存储在“堆(heap)”里,用堆进行存储分配比用栈进行存储分配需要更多的时间
4、Java的对象存储在堆里,对象的引用存储在栈里,但基本类型是特例,基本类型的对象是存储在栈里的
[@more@]
5、九种基本类型:boolean、char(16-bit)、byte(8-bit)、short(16-bit)、int(32-bit)、long(64-bit)、float(32-bit)、double(64-bit)、void,JAVA的基本类型的位数是不会变化的,它只与虚拟机有关,与机器具体的参数无关
6、对应九种包装器类型:Boolean、Character、Byte、Short、Integer、Long、Float、Double、Void(即大写了类型名首字母,就成为了包装器类),还有其它类似的包装器,但可能没有对应的基本类型,比如两个用于高精度计算的类:BigInteger(支持任意精度的整数)和BigDecimal(支持任意精度的浮点数),它们的运算不能使用运算符,只能调用方法,速度较慢,但可以实现高精度,按常理来考虑就可以想到,使用包装器来进行一些操作,必然会比直接使用基本类型慢,但是肯定也会有其它方面的好处,比如功能的扩展。
7、九种基本类型对应的的默认值:false、null、(byte)0、(short)0、0、0L、0.0f、0.0d,void型不清楚,基本类型只有在作为某个类的属性时才有初始值,其它情况编译器是不管它的,没有经过初始化的变量可能是任意值,编译将无法通过,会产生未初始化的错误(编译时错误)。
8、Java中所有数值类型都有正负号,不存在无符号的数值类型,boolean型所占存储空间的大小没有明确指定,其值只能为true和false
9、定义基本类型:char c = 'x'; 或:Character C = new Character('x');
10、Java会确保数组被初始化且有越界检查
11、创建一个数组对象时,实际是创建了一个引用数组,每个引用会自动被初始化为一个特定值null,null表示引用还没有指向任何对象。在使用引用前必须为其指定一个对象,如果试图使用一个还是null的引用,将会在运行时报错。(即item2中所说的情况,注意,不是报编译错误,编译是可以通过的)
12、创建基本类型数组时,编译器会将数组所占的内存全部置零(类型默认值)。(即,基本类型数组置零,对象数组置null)
13、Java是一种自由格式(free-form)的语言,空格、制表符(tab)、换行(enter)都不会影响程序的执行结果
14、基本类型变量的生命周期受限于作用域(scope),超出作用域就不可用了;对象在作用域之外仍然存在,定义时的引用虽然已经不可用,但可在那之前传递或复制引用
15、类内部的元素包括:数据成员(data member,有时也叫做域(field)),方法(method,有时也叫做成员函数(member function))
16、当变量作为一个类的成员使用时,Java会确保给定其默认值,但是如果变量不是类的成员变量,比如定义在某个方法内的变量,是不会被自动初始化的
17、调用方法时,如果参数是对象,则传递的是对象的引用,如果参数是基本类型的,则传入的是值
18、Java的包(package)使用反向域名来命名,包名一律小写
19、static的方法或变量是归属于类(class)的,类的多个对象共享同一个static变量,static方法常被用来看护与其隶属于同一类型的实例群(比如计算这个类已经生成了多少个对象)
20、java.lang(是指一个类,不是指这个包)是默认被import到每一个java文件中的,所以不需要手动import它
21、常用到的System.out是一个static的PrintStream对象
22、java文件名必须与其中一个public类名相同,且该类中必须包含一个public static void main()方法,这是程序执行的起点
23、Java注释文档的javadoc命令都只能始于/**注释,结束于*/;可以使用一些文档标签,它们是一些以@字符开头的命令,且@字符要置于注释行的最前面(但在前导*之后);行内文档标签则可以出现在javadoc注释中的任何地方,它们也是以@开头的,但要括在{}内
24、javadoc只能为public和protected成员进行文档注释,private和package成员的注释会被忽略掉
25、javadoc注释中可以嵌入html标签,主要可用于对代码进行格式化


数据的六种存储位置:寄存器、栈、堆、静态存储、常量存储、非RAM存储
[@more@]
1. 寄存器(register)。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。(先不用考虑它了)

2. 堆栈(stack,也简称为栈。位于通用RAM(random-access memory,随机访问存储器,就是内存)中,但通过它的“堆栈指针”可以从处理器那里获得直接支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,Java 编译器必须知道存储在堆栈内所有数据的确切大小和生命周期,因为它必须生成相应的代码,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些Java 数据存储于堆栈中——特别是对象引用,但是Java 对象并不存储于其中。(对象的引用存在栈里,但对象不在)

3. 堆(heap)。一种通用性的内存池(也存在于RAM 区),用于存放所有的Java 对象。堆不同于堆栈的好处是:编译器不需要知道要从堆里分配多少存储区域,也不必知道存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当你需要创建一个对象时,只需用new 写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。当然,为这种灵活性必须要付出相应的代价。用堆进行存储分配比用堆栈进行存储存储需要更多的时间。(C++中可以用栈保存对象)

4. 静态存储(static storage),是一段特定存储区。这里的“静态”是指“在固定的位置”(尽管也在RAM 里)。静态存储里存放程序运行时一直存在的数据。你可用关键字Static 来标识一个对象的特定元素是静态的,但Java 对象本身从来不会存放在静态存储空间里。(对象的特定元素可以标记为static,但不能把对象整体标记成static)

5. 常量存储(constant storage)。常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。(可以把常量看作是代码的一部分)。有时,在嵌入式系统中,常量本身会和其它部分隔离开,所以在这种情况下,可以选择将其存放在ROM(read-only memory,只读存储器)中。

6. 非RAM 存储(non-RAM storage)。如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中两个基本的例子是“流对象(streamed object)”和“持久化对象(persistent object)”。在“流对象”中,对象转化成字节流,通常被发送给另一台机器。在“持久化对象”中,对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。这种存储方式的技巧在于:把对象转化成可以存放在其它媒介上的事物,在需要时,可恢复成常规的、基于RAM 的对象。Java 提供对轻量级持久化(lightweight persistence)的支持,未来的Java 版本可能会为持久化提供更全面的解决方案。

猜你喜欢

转载自zhyp29.iteye.com/blog/2305100