第2章 一切都是对象
尽管Java是基于C++的,但是相比之下,JAVA是一种更纯粹的面向对象程序设计语言。
2.1 用引用来操纵对象
每种编程语言都有自己的操纵内存中元素的方式。
所有的一切在JAVA里都得到了简化。一切都被视为对象。操纵对象的实际上是对象的一个引用。可以想象用遥控器(引用)来操纵电视机(对象)。当有人想要改变频道时,实际操纵的是遥控器,再由遥控器来调控电视机。我们四处走动,只需要携带遥控器而不是电视机。
注意,我们始终操控的是遥控器,而不是电视机。都是由遥控器来调控电视机的。
即使没有电视机,遥控器亦可独立存在。也就是引用,并不需要有一个对象与它关联。
只不过,如果这时使用引用,会报错。 因此需要初始化。
String s="asdf";
这里有个特性:字符串可以用带引号的文本初始化。但是对象一般采用其他的初始化方法。
2.2 必须由你创建所有对象
通用与对象关联的初始化方法:
String s=new String("asdf");
2.2.1 储存到什么地方
寄存器
最快的存储区。它位于处理器内部。因数量有限,寄存器是按需分配的,你不能控制,也感觉不到。堆栈
位于RAM中。一般存放对象引用。
约束:创建程序时,Java系统必须知道存储在堆栈内所有项的确切生命周期,以便移动堆栈指针。堆
通过内存池(RAM中),用于存放所有的JAVA对象。
好处:编译器不需要存储的数据在堆里存活多长时间。常量储存
常量值通常只么放在程序代码内部,因为永远不会改变非RAM存储
存活于程序外,不受程序的任何控制。例子,流对象和持久化对象。在流对象中,对象转化成字节流,发送给另一台机器。持久化对象中,对象放在磁盘中。
好处:把对象放在其他媒介上。需要时,恢复为基于RAM的对象。
一个重要的点,基本类型、对象引用放在堆栈中,对象放在堆中。举例: String是一个不变的量,放在常量池中。如果是new出来的String对象是要放在堆中,String引用放在堆栈中。
Java中字符串内存位置浅析
2.2.2 特例:基本类型
基本类型: 不用new来创建变量,而是创建一个并非是引用的“自动”变量,这个变量直接存储“值”,并置于堆栈中,因此更加高效。
JAVA确定每种基本类型所占存储空间的大小。
基本类型具有包装器类,这样可以在堆中创建一个非基本对象。
高精度数字
JAVA提供两个用于高精度计算的类:BigInteger 和BigDecimal。
这两个类提供的操作与对基本类型所能执行操作相似,但是需要以方法来代替运算符方式来实现。
BigInteger: 支持任意精度的整数
BigDecimal:支持任何精度的浮点数。
这两个类是很有作用的,比如当你涉及到类似电商的时候
2.2.3 Java中的数组
JAVA会确保数组会被初始化,并且它的范围外无法被访问。
这种范围检查,是以每个数组上少量的内存开销及运行时的下表检查为代价的。
2.3 永远不需要销毁对象
JAVA怎样完成清理工作?
2.3.1 作用域
作用域决定了在其内定义的变量名的可见性和生命周期。作用域由花括号的位置决定。
JAVA不存在C++的类似作用域覆盖的情况。
2.3.2 对象的作用域
JAVA对象不具备和基本类型一样的声明周期。即它可以存在于作用域之外。
注意,这里说的存在,但并不代表可以使用。
举例
![Upload 图片.png failed. Please try again.]
引用在作用域结束时消失了,之后我们无法访问这个对象。然而存在堆中的String对象仍然存在。
这就解决了C++的许多编程问题。在C++中,你不仅必须要确保对象的保留时间与你需要这些对象的时间一样长,在使用完后,需将其销毁。
这里有一个问题,如果一直存在,内存空间满了怎么办?
JAVA会有一个垃圾回收器,用来监视用new创建的所有对象,辨别不会再被引用的对象(也就是作用域结束的对象)。随后释放这些对象的内存空间。消除了“内存泄露”的问题。
2.4 创建新的数据类型:类
2.4.1 字段和方法
一旦定义了一个类,类中有两种类型的元素:数据成员和方法。
- 每个对象都有用来储存其字段的空间,普通字段不能在对象间共享。
- 使用句点引用对象成员。如:data.i=48;
基本成员默认值
- 若类的某个成员是基本数据类型,即使没有进行初始化,也会有默认值。但是注意,最好自己初始化。
![Upload 图片.png failed. Please try again.]
- 这种默认值只针对类的字段。
2.5 方法、参数和返回值
Java的方法决定了一个对象能够接收什么样的消息(即别人对它的调用)。基本组成为:名称、参数、返回值、方法体。
- JAVA的方法只能作为类的一部分来创建。方法只能通过对象才能被调用。
- 调用方法的行为被称为发送消息给对象。面向对象的程序设计通常简单地归纳为“向对象发送消息”。上面的例子,消息是f(),对象是a.
2.5.1 参数列表
方法的参数列表指定要传递给方法什么样的消息。
参数采用的是对象的形式,这里传递的是引用。
到此为止,会认为:程序似乎只是一系列带有方法的对象组合,这些方法以其他对象为参数,并发送消息给其他对象。大体如此。
其实一个完整的JAVA程序就是如此。举例像JAVA WEB,后端使用的就是JAVA,提供一系列的服务,通过类对服务进行划分,一个类是某类型服务的集合,后端由这些类组合,印证了前面说的对象即服务。
2.6 构建一个JAVA程序
在构建之前,还需要了解一些问题。
2.6.1 名字可见性
不同的模块中有相同名字的变量,如何保证区分两个名字并且防止二者相互冲突?
这里介绍的是命名空间的概念。引入了包的概念。如:com.edu.util.
这个机制保证了所有文件能够自动存活于自己的命名空间中,而且同一个文件哪每个类都有自己的唯一标志符。
2.6.2运用其他构件
解决向前引用的问题,即类在文件的后面定义,也可以直接使用
使用import来引入其他类库,也就是俗称的导包。
2.6.3 static关键字
执行new来创建对象时,数据存储空间才被分配。
如果想要没有创建对象,也能调用这个方法,需要使用static。
当声明一个事物是static时,意味着它不会与它所在的类的任何对象关联在一起。
也就是说,为什么非得创建一个对象,才能使用方法和字段。因为非static域的字段和方法都是和特定的对象绑定的。如果你想不创建对象,直接使用方法和字段,就设定static,这样没有和特定对象绑定,直接用就好了,不用创建对象。
举个例子,创建一个类叫长方形。里面有字段长宽高。 长宽高这三个属性一定是非static的,因为肯定是和特定的对象绑定在一起。 比如3*5*8的长方形对象,5*6*8的长方形对象,不和特定的对象绑定在一起没有意义。但是如果现在有个需求,我想知道我创建了多少个长方形,设有一个属性叫数量,那么这个属性就不能与特定对象绑定,它应该是长方形这个类独有的,故设为static。
- 使用: 直接类名+方法名即可。
2.7 你的第一个JAVA程序
- java.lang 是默认导入到每个类文件中的,它的所有类是可以被直接使用的。
2.7.1 编译和运行
要有一个开发环境,并且安装好。
需要设定路径信息,以确保计算机能够找到javac和java这两个文件。(常说的设置环境变量)
javac 是编译命令,java 是运行命令。
2.8 注释和嵌入式文档
三种注释风格
2.8.1 注释文档
问题
代码文档撰写的最大问题就是文档的维护。如果代码与文档分离,那么每次修改代码也需要修改相应文档,并不方便。由此产生了,javadoc。
它将代码和文档放在一起。使用特殊的注释语法来标记文档。此外使用一个工具,用于提取这些注释。
2.8.2 语法
- 所有的javadoc命令只能在/**的注释中出现。
- 使用javadoc有两种:嵌入HTML或使用文档标签。
- javadoc只能为public 和protected成员进行文档注释。
- 将会输出一个HTML文档。
2.8.3 嵌入式HTML
顾名思义,就是在注视中使用HTML的标签来确定格式。
2.8.4 一些标签示例
介绍一些常用的javadoc标签,这些标签在看源码是会经常看到。
- @see:引用其他类:在生产的HTML文件中,可以通过这个标签链接到其他文档。
2.{@link package.class#memeber label} :与@see相似
3.{@docRoot} :产生到文件根目录的相对路径。
4.@version : 存放版本信息
5.@author :作者
6.@since: 允许指定程序代码最早使用版本。
7.@Param :是用来描述方法中参数列表。
8.@return :描述返回值的含义
9.@throws :调用失败后抛出的对象。
10.@Deprecated :弃用的意思。指出一些旧特性被新特性取代,不要使用这些特性,可能会被删除。
- 生成javadoc文档:javadoc [options] [packagenames] [sourcefiles] [@files]
2.9 编码风格
- 类名的首字母大写。使用驼峰风格。
- 方法、变量名等地一个字母小写。