Java编程思想 4th 第2章 一切都是对象
Java是基于C++的,但Java是一种更纯粹的面向对象程序设计语言,和C++不同的是,Java只支持面向对象编程,因此Java的编程风格也是纯OOP风格的,即一切都是类,所有事情通过类对象协作来完成。
在Java中,使用引用来操纵对象,在Java编程思想的第四版中,使用的术语是“引用(reference)”,之前有读过Java编程思想第三版,在第三版中,使用的术语是“句柄(handle)”,事实上,我觉得第三版的术语“句柄”更加形象传神,就像你用一个门的把柄来开门关门一样,不用管门是什么门,总之你用门把柄就能控制操作这扇门。当然,使用“引用”这个术语对于C++出身的人来说更方便理解,因为在C++中,底层一般使用指针来实现引用,也即通过指针来间接操纵对象。更合拍的是,在C++中,使用new动态分配的对象是匿名的,没有任何办法能够操纵该对象,除了起初new表达式返回的指针,在Java中,对象都是new出来的,是存放于动态内存中的,要想使用对象,就要通过对象的句柄(引用)来操作,这无形中把Java和C++联系了起来,因为二者本质都是一种类似指针的东西。
在Java中,引用可以单独存在,就像在C++中,指针也是一个独立的存在。我们可以把引用关联到对象上,也可以令指针指向对象,因此引用(指针)是独立于对象存在的。同指针一样,不能够随意使用没有关联对象的引用。在Java中,使用未关联对象的引用会导致编译报错;在C++中,这通常会导致内存越界,进而收到操作系统的segmentfault信号,如果未捕捉处理该信号,默认是程序coredump。如下图所示:
C++:

Java:

此处还隐式说明了一个Java语言的特性:String字符串可以用带引号的字面值进行初始化(字面值一词是我从C++中拿过来的术语),示例如下:
String str = "Hello";
一旦创建了引用,除了用上述特性直接进行初始化,通常情况下引用必须管理到一个对象,而Java中对象的创建只能通过new来进行。对于上述例子,可以写成:
String str = new String("Hello");
C++中与寄存器有关的是volatile关键词,然而C++并不能直接操纵寄存器,仅仅通过volatile来阻止编译器利用寄存器可能的优化。除了汇编语言能够直接操纵寄存器,其他的高级语言都无法做到,Java也不例外。
Java会将对象的引用也即“指针”存放在栈中,栈的优点是快,系统自动管理,缺点是大小有限制,就像C++一样,如果栈的用量过大会导致爆栈。
Java会将对象存放在堆中,就是那些new出来的对象,堆的优点是空间大,缺点是程序员的心智负担大,需要自己手动分配和回收资源,如果一直申请堆内存而不及时释放,最终会耗尽系统可用内存(当然在Java世界中不需要程序员手动管理,这一切交给gc垃圾回收系统)。
Java程序和C++程序一样,除了用到的对象及数据外,还有代码指令本身,它也需要被加载到内存。在C++中,代码指令通常存储在text段中,Java也是如此。text代码区的特点是只读不可写,可能会被多个程序共享。
除了高速的寄存器和内存,计算机还有一个海量的、持久化的存储设备:硬盘。硬盘独立于程序之外,可以将一些数据写入到硬盘进行存储,待下次使用时从硬盘中加载读取。
无论Java如何抽象,如何面向对象编程,它最终还是需要数学世界的基本类型来提供用于高级语言抽象的基石。Java中的基本类型是存放在栈中的(之所以放在栈中而不是堆中,我觉得并不是书本所说的效率问题,栈和堆的本质区别是生命周期的长短,如果所有的一切都放在长生命周期的堆中,Java程序很快就会吃光内存,这是不可能接受的行为),它们与对象及其引用不同,基本类型的变量就是对应一个值,不同的变量之间拷贝赋值时,不会像引用那样只是拷贝了引用。Java基本类型所占空间大小是固定的,不随不同硬件平台变化,并且不会像C++那样有有符号和无符号之分。具体如下:
| 基本类型 | boolean | char | byte | short | int | long | float | double | void |
| 内存大小 | 未定义 | 16 bits | 8 bits | 16 bits | 32 bits | 64 bits | 32 bits | 64 bits | 无 |
| 对应封装类 | Boolean | Character | Byte | Short | Short | Long | Float | Double | Void |
因为内置的基本类型是存储在栈中的,且仅仅是一个基本类型,不具有其他功能,为了实现更多功能,Java为每个基本类型进行了封装,以提供更多更好用的功能,且封装后的类型的实例化对象是存储在堆中的,可由垃圾回收管理来自动回收对象所耗用的内存。
在基本类型和其封装类型之间可以相互转换,比如:
Character ch1 = 'x';
Character ch2 = new Character('y');
char c = ch1;
除了对每个基本类型进行封装提供对应的包装类,Java还提供了2个用于数值范围大、精确度高的包装类:BigInteger和BigDecimal。这两个封装内没有对应的基本类型,它们运算速度较慢,牺牲了速度,换取了精度。
Java数组和C++不同,Java会确保数组读写不会溢出以及初始化,数组既可以存储基本类型,也能存储对象的引用。当存储对象引用时,它们被初始化为null值,编译器会在数组元素被访问时检查元素是否为null以阻止使用未初始化元素的问题。对于内置类型,如若未初始化,则默认置零。
Java和C++一样具有作用域的概念,并且两者作用域的规则相同,唯一不同的是,Java禁止内层的变量名或者引用覆盖外层变量名/引用,这是比C++安全的一个规定,可以阻止用户不经意的误用。
Java虽然和C++一样具有作用域规则,但作用域生效的对象是基本类型的变量或者对象的引用,而引用所绑定的对象本身则不受作用域限制。
Java中一切都是对象,对象的类型决定对象的状态和行为,也即我们需要定义一种类型,该类型可以被实例化出一个对象,每个对象都有自己的状态和行为,而我们定义的类型是对这些实例化对象的抽象。定义新类型的语法如下:
class TypeName {
//class body
}
与C++不同的是,Java的类定义不需要以分号结束。
定义类型时需要定义该类型所实例化出来的对象的状态和行为。所谓状态也即数据存储,每个对象都有自己的私有数据,数据存储的信息反应出状态;所谓行为也就是函数方法,同一类对象都能用相同的函数方法去操纵。在Java中数据状态称为field,函数方法称为method。
定义field时,field可以是基本类型,也可以是对象引用,对于前者Java会确保没有初始化的获得一个默认值,对于后者,引用必须初始化。类值类型的默认值全部置零,对于boolean类型来说,默认值为false。
method就是一个函数,其结构是函数的四要素:返回值、函数名、参数列表和函数体。前三者唯一的标识一个函数,也称为函数签名或方法签名。Java中的method必须定义在class内部,否则编译报错。函数一定要有return语句(当然由于历史原因少数使用C语言的“老顽固”为了省事对返回类型为void的函数是不写return语句的,此时由编译器默认插入),return语句的作用有两个,一是转移控制权,另一个是返回一个值。
Java中使用import来导入一个包,也即一个类库,因为Java中所有代码都写在class内部,所以一个Java库也称为类库。除了一次导入一个包,也可以用通配符*来导入一群库。
Java除了有定义在method内部的局部变量以及每个对象都有的field之外,还有第三种变量,那就是static变量。Java中的static变量同C++相同,它改变了static修饰的变量的存放位置,也改变了修饰的变量的生存周期。在Java中,static修饰的变量只能是field,而不能是method内部的local局部变量。static修饰后的变量不再为每一个对象都复制一份,而是整个class类对象共享同一份,因此其访问方式也发生了变化,因为它是属于类本身的,而不是对象本身的,所以可以通过类名直接访问。又因为整个class类对象都共享它,因此也可以通过类对象来访问。和C++不同,当通过类名来访问时,Java使用点运算符,而C++使用作用域运算符来访问。
Java每一个程序会默认导入java.lang包。Java类的名字必须与文件名相同,这也暗示了一个Java源文件只能有一个public类。
Java的注释继承了C/C++的两种风格,一是单行注释//,二是多行注释/*注释内容*/。另外Java还支持文档注释。
Java编程思想 4th 第2章 一切都是对象的更多相关文章
- Think in Java(Java编程思想)-第2章 一切都是对象
1. String s = "asdf"//创建一个String引用,并初始化. String s = new String("asdf")//创建一个新对象, ...
- 《Java编程思想》笔记 第二章 一切都是对象
1.对象存储位置 对象的引用存在栈中,对象存在堆中.new 出来的对象都在堆中存储.栈的存取速度较快. 所有局部变量都放在栈内存里,不管是基本类型变量还是引用类型变量,都存储在各自的方法栈中: 但是引 ...
- Java编程思想 4th 第1章 对象导论
所有编程语言都提供抽象机制. 面向对象编程似乎是一种很好的编程思想和方式,面向对象编程中的对象简洁描述是:对象具有状态.行为和标识.状态指的是数据存储,存储的数据能反应状态:行为指的是方法,方法表示对 ...
- Java编程思想 4th 第3章 操作符
有了数据,还需要进行数据间的运算,因此Java中也有数据间运算的各种符号,书本称之为操作符,正确的翻译应该是运算符. Java中的运算符同C++相同,运算符同运算符对象构成表达式,表达式是运算对象及运 ...
- 《Java编程思想》第一二章
前段时间一直通过网络教程学习Java基础,把面向对象部分学完之后本来打算继续深入学习,但是感觉自己操之过急了,基础根本不够扎实,所以入手了一本<Java编程思想>,希望先把基础打好,再深入 ...
- Java编程思想学习杂记(1-4章)
程序流程控制 移位运算符 移位运算符面向的运算对象是二进制的位,可单独用它们处理整数类型.左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)." ...
- 《Java编程思想》笔记 第一章 对象导论
1.抽象过程 Q:什么是对象??? A: 1) 万物皆对象 --- 对象具有状态,行为和标识 2)程序是对象的集合,他们通过发送消息来告诉彼此要做的 3)通过创建包含现有对象的包的方式来创建新类型 ...
- Java编程思想读书笔记 第一章 对象导论
抽象过程 纯粹的面向对象程序设计方式: 万物皆为对象: 对象可以存储数据,还可以在其自身执行操作 程序是对象的集合: 通过发送消息告诉彼此要做的 每个对象都有自己的由其它对象构成的存储:可以在程序中构 ...
- 《Java编程思想》笔记 第九章 接口
1.抽象类和抽象方法 抽象方法,仅有方法声明没有方法体 abstract class AbstractClass{ abstract void f(); //没有 {} } 只要有一个或者多个抽象方法 ...
随机推荐
- 【Linux笔记】CentOS 7 systemctl、firewalld
一.CentOS7 systemctl 在CentOS7中,进行chkconfig命令操作时会发现有类似“systemctl.....”的提示,systemctl可以简单实现service和chkco ...
- java super
用法: 1.子类构造器里面默认调用父类构造器 2.调用父类的属性,方法
- Windows平台下在服务中添加MySQL
widows下查看服务 1.桌面计算机-->右键-->管理-->计算机管理(本地)--->服务和应用程序-->服务 2.运行 中输入 services.msc 在服务中添 ...
- Unity使用C#实现简单Scoket连接及服务端与客户端通讯
简介: 网络编程是个很有意思的事情,偶然翻出来很久之前刚开始看Socket的时候写的一个实例,贴出来吧 Unity中实现简单的Socket连接,c#中提供了丰富的API,直接上代码. 服务端代码: [ ...
- Mybatis笔记六:Mybatis中SqlSessionFactoryBuilder/SqlSessionFactory/SqlSession/映射器实例的作用域(Scope)和生命周期
SqlSessionFactoryBuilder 这个类可以被实例化.使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了.因此 SqlSessionFactoryBuilder ...
- 沉迷AC自动机无法自拔之:穿越广场 square
如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 穿越广场 [问题描述] L 国的仪仗队要穿越首都广场了.首都广场可以看做是一块 N*M 的矩形网格,仪仗队 ...
- 浅谈Tarjan算法及思想
在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连 ...
- loj2540 「PKUWC2018」随机算法 【状压dp】
题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...
- 团体程序设计天梯赛 L1-009. N个数求和
易错题 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdboo ...
- interface思考练习一
参考了这篇文章,博主超级优秀,看他的最好,我只是写了点自己看他的博文学到的东西.CSDNzdwzzu2006 接口这东西认真学是在第一次构建工程的时候,很晕菜,原来学SE时不扎实,导致东西都不会用,看 ...