您的位置:首页 > 编程语言 > Java开发

Java学习笔记——一切都是对象

2013-08-20 08:27 218 查看
本文为Java编程思想第四版的学习笔记,在此感谢作者Bruce Eckel给我们带来这样一本经典著作,也感谢该书的翻译及出版人员。本文为原创笔记,转载请注明出处,谢谢。

1.用引用操纵对象

每种编程语言都有自己的操纵内存中元素的方式,在Java中,一切都被视为对象,因此可以采用单一固定的语法。尽管一切都看做对象,但是操纵的标识符实际上是对象的一个“引用”。简单的例子如,电视遥控器(引用)和电视机(对象)。即使没有电视机,遥控器亦可独立存在,也就是说,你拥有一个引用,并不一定需要有一个对象与它关联。如:

String s;

这里所创建的只是引用,并不是对象。如果此时向s发送一个消息,就会返回一个运行时的错误。

对于引用的一点个人理解:学过C++的人都知道,在C++中也有引用的概念。起初,本菜鸟并不知道C++中的引用和Java中的引用是有不同的,也经常混淆。实际上,C++中引用的概念更倾向于是对象的一个别名,相当于我们给“张三”起了个别名叫“老张”。C++程序不会在内存中为引用分配存储空间,因为这仅仅是一个别名。相比之下,Java中的引用的概念更像是C语言中的指针(Java中并没有指针的概念),在Java中,当我们创建一个引用时,程序会在内存的栈中为该引用分配存储空间;当我们将我们创建的引用与实际对象相关联起来的时候,实际上是将对象的地址复制到了引用所在的存储空间中;通过引用(实际上是通过这个存储空间内保存的地址)我们可以找到与该引用相关联的实际对象,从而对对象执行相关操作。

2.必须由你创建所有对象

2.1存储到什么地方

Java程序运行时,对象是怎么进行放置安排的呢?特别是内存是怎样分配的呢?

有五个不同的地方可以存储数据:

1)寄存器。这是最快的存储区,因为它位于处理器内部。但是寄存器的数量极其有限,所以寄存器根据需求进行分配。你不能直接控制寄存器,也不能在程序中感觉到寄存器存在的任何迹象。(另一方面,C和C++允许你想编译器建议寄存器的分配方式)

2)(译者翻译为堆栈,实际英文中即为stack)。位于通用RAM(随机访问存储器)中,通过栈指针可以从处理器那里获得直接支持。栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,Java系统必须知道存储在堆栈内所有项的确切生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些Java数据存储于堆栈中——特别是对象引用,但是Java对象并不存储于其中。

3)堆。一种通用的内存池(也位于RAM中),用于存放所有的Java对象。堆不同于栈的好处是:编译器不需要知道存储的数据在堆里存活多长时间,因此,在堆里分配存储有很大的灵活性。当然,为这种灵活性必须要付出相应的代价:用堆进行存储分配和清理可能比用栈进行存储分配需要更多的时间(如果确实可以在Java中像C++一样在栈中创建对象)。

4)常量存储。常量值通常直接存放在程序代码内部。这样做是安全的,因为它们永远不会被改变。

5)非RAM存储。如果数据完全存活于程序之外,那么他可以不受程序的任何控制,在程序没有运行时也可以存在。其中两个基本的例子是流对象和持久化对象。这种存储方式的技巧在于:把对象转化成可以存放在其他没接上的事物,在需要时,可恢复成常规的、基于RAM的对象。

关于Java中的存储问题,本菜鸟会在今后结合对Java虚拟机规范学习之后做详细的分析。

2.2特例:基本类型

由上面的内容我们可以简单的这样认为:Java中所有的对象都存储于堆中。实际上,在程序设计中经常要用到一系列类型,它们需要特殊对待。可以把它们想象为”基本“类型。之所以特殊对待,是因为new将对象存储在”堆“里,故用new创建一个对象——特别是小的、简单的变量,往往不是很有效。因此,对于这些类型,Java才去与C和C++想通的方法。也就是说,不用new来创建变量,而是创建一个并非是引用的”自动“变量。这个变量直接存储”值“,并置于堆栈中,因此更加有效。

Java要确定每种基本类型所占存储空间的大小。他们的大小并不像其他大多数语言那样随机器硬件架构的变化而变变化。这种所占存储控件大小的不变性是Java程序比用其他大多数语言编写的程序更具有可移植性的原因之一。下表为Java中的八种基本数据类型:

从表中我们可以看出,Java中的基本数据类型有如下特点:
1)所有数值类型都有正负号,所以不要去寻找无符号的数值类型;
2)boolean类型所占存储空间的大小没有明确规指定,仅定义为能够取字面值true或false;
3)基本类型具有与之对应的包装器类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。Java SE5的自动包装功能将自动滴将基本类型转换为包装器类型:
Character c='x';
Character ch = new Character(c);
并可以反向转换:char c = ch;

2.3高精度数字
在实际应。用中,有时我们也许需要很大的整数(它超过了long所表示的范围)或者精度要求很高的浮点数(用程序计算0.2+0.4所得到的结果并非0.6,这是一个有趣的事)。Java提供了两个用于高精度计算的类:BigInteger和BigDicimal。虽然他们大体上属于”包装器“类的犯愁,但二者都没有对应的基本类型。这两个类包含的方法,提供的操作与对基本类型所执行的操作相似,只不过必须以方法调用方式取代运算符方式来实现。由于这么做复杂了很多,所以运算速度会比较慢。在这里,我们以速度换区了精度。

2.4Java中的数组
几乎所有的程序设计语言都支持数组。在C和C++中使用数组是很危险的,因为C和C++中的数组就是内存块。Java的主要目标之一是安全性,Java确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下标检查为代价的。但由此换来的是安全性和效率的提高,因此付出的代价是值得的(并且Java有时可以优化这些操作)。
当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会被自动初始化为一个特定值,改制拥有自己的关键字null。还可以创建用来存放基本数据类型的数组,同样,编译器也能确保这种数组的初始化,因为它会将这种数组所占的内存全部清零。

3.永远不需要销毁对象
在大多数程序设计语言中,变量生命周期的概念,占据了程序设计工作中非常重要的部分。变量生命周期的混乱往往会导致大量的程序bug,这里将介绍Java是如何替我们完成所有的清理工作,从而大大地简化这个问题。
3.1作用域
大多数过程型语言都有作用域的概念。作用域决定了在其内定义的变量名的可见性和生命周期。在C和C++和Java中,作用域由花括号的位置决定。例如:
{
int x = 12;
//Only x available
{
int q = 96;
//Both of x & q available
}
//Only x available
//q is "out of scope"
}
在作用域里定义的变量之可用于作用域结束之前。
尽管以下代码在C和C++中是合法的,但是在Java中却不能这样书写:
{
int x = 12;
{
int x = 96;//Illegal
}
}
编译器会报告变量x已经定义过。所以,在C和C++里讲一个较大作用域的变量”隐藏“起来的做法,在Java里是不允许的。

3.2 对象的作用域
Java对象不具备和基本类型一样的生命周期。当用new创建一个Java对象时,它可以存活于作用域之外。所以假如你采用代码:
{
String s = new String("a string");
}//End of scope
引用s在所用于重点就消失了。然而s指向的String对象人继续占据内存空间。
事实证明,由new创建的对象,只要你需要就会一直保留下去。这样,许多C++编程问题在Java中就完全消失了。在C++中,你不仅不需要确保对象的保留时间与你需要这些对象的时间一样长,而且还必须在你使用完它们之后,将其销毁。Java有一个垃圾回收器,用来监视用new创建的所有对象,并辨别哪些不会再被信用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。

4.创建新的数据类型:类
这里问题比较基本和简单,仅作罗列:类,创建对象,字段和方法,基本成员默认值,方法、参数和返回值、参数列表等。

5.构建一个Java程序
5.1 名字可见性:在自己的包前加入域名
5.2 运用其他构件:import关键字
5.3 static关键字
通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则实际上并未获得任何对象。执行new来创建对象时,数据存储控件才被分配,其方法才供外界调用。
static用来解决上述方法无法解决的两种情形:
1)只想为某特定域分配歹意存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象;
2)希望某个方法不与包含它的类的任何对象关联在一起,也就是说没有创建对象,也能够调用这个方法。
只需要将static关键字放在定义之前,就可以将字段或方法设定为static。如:
class StaticTest {
static int i = 47;
}
现在,即使你创建两个StaticTest对象,StaticTest.i也只有一份存储空间,这两个对象共享同一个i。

引用static变量有两种方法:一种是通过一个对象去定位它,如st.i;另一种是通过其类名直接饮用,而这对于非静态成员则不行。

6.你的第一个Java程序

7.注释和嵌入式文档
7.1 Java中有两种注释风格,一种是传统的C语言风格,如:
/*This is a comment
*That continues
*across lines
*/
另一种也源于C++,这种注释是单行注释 //

7.2 注释文档
Java中提供了Javadoc工具,通过该工具我们可以将满足Javadoc语法的注释提取出来,生成一个便于查阅的HTML文档。所有javadoc命令都只能在/**注释中出现,和通常一样,注释结束于*/。共有三种类型的注释文档,分别对应于注释位置后面的三种元素:类、域和方法。javadoc只能为public和protected成员进行文档注释。private和包内可访问成员的注释会被忽略掉。

7.3 嵌入式HTML
javadoc通过生产的HTML文档传送HTML命令,这使你能够充分利用HTML。当然,主要目的还是为了对代码进行格式化。

7.4 一些标签实例
网上很容易查找,在此不再赘述。

总结:本章为基础性知识,主要结合面向对象的思想简单地介绍了Java中的引用、对象的存储、销毁、类、static关键字的使用、Java注释等基础性知识,文中引导读者创建了一个简单的Java程序,并在控制台通过javac进行编译,通过java命令进行执行。重难点为:对象的存储、static关键字的使用以及基本数据类型等相关知识。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: