《编程导论(Java)·4.1数据抽象的含义》

You have no choice about the necessity to integrateyour observations,

your experiences, your knowledge into abstractideas, i.e., into principles.

——Ayn Rand, 《Philosophy: Who Needs It》 1974

数据抽象(Data abstraction)是将数据类型的抽象特征与事实上现的详细细节清晰地分离。

当中数据类型的“抽象特征”是指对用户代码而言可见的、怎样使用该数据类型的接口。数据抽象是接口与实现分离原则在类型层面以及对象技术中的推广

本章将介绍作为数据抽象的Java基本数据类型、抽象类、Java接口;重点讨论抽象类、接口的作用。

下一章继续介绍数据抽象——作为抽象数据类型的线性表及事实上现。


4.1数据抽象的含义

内存中保存的数值被称为数据或操作数,对数据进行分类是为了方便程序猿识别和操作它们。在[2.2.2 Java数据类型] 中,介绍了若干的概念:数据类型——定义一个值的集合以及处理这个值集的一组操作。Java语言的类型包含基本类型和程序猿自己定义的数据类型(引用类型)。

在[3.2.2 操作符]中,介绍了基本类型的各种操作;而在[2.4.1 引用的涵义]中列举了引用类型的7种操作。须要注意的是。上述全部的介绍均处于Java语言的层面[而非JVM层面]。

或者说,一直讨论的是Java数据类型的抽象特征——接口。

4.1.1 基本类型的实现

基本类型的接口/抽象特征包含该类型的取值范围和适用操作符。这里以最经常使用的int和boolean为例,说明数据抽象的含义。

1. int类型的接口和实现

【这里先介绍int使用的一些注意事项】整数类型int是对数学整数的模拟。int与数学整数的区别在于int不是无限的。int类型逻辑上拥有32位内存空间,依照[0.1.2 二进制补码]。int类型的最大值(补码)为(231 -1)即2147483647或0x7FFF_FFFF,或二进制的0b01111111_11111111_11111111_11111111。当它加上1,就变成了0x8000_0000即最小值(-231即-2147483648)。

通常把整型的计算形容为在时钟的钟面上执行。计算时超过最大值或最小值的情况。称为溢出(O
verflow与underflow),当使用大数字时。要小心溢出。由于没有不论什么人或异常机制帮助程序猿防止这样的程序错误的发生,它是一个沉默的杀手。

可用例如以下代码验证:

void doSth(){

int x=0x7FFFFFFF;

System.out.println( x + 1 );

}

此外,int中什么值能够使i == -i呢?除了零之外,还有最小值0x8000_0000。

因此if(i == -i)的语义不同于if(i == 0)。

对于int的操作。包含了大多数操作符,如算术、比較、位操作、赋值和一元操作的正负号、++、--等等。

上述内容均为int的接口/抽象特征。作为int的用户,说int类型(逻辑上)拥有32位内存空间时。意味着用户知道了int的值域范围

其实。JVM规范中规定了int的值域范围,可是并未定义int类型的内存空间。用于储存int数据的内存空间,由JVM的不同实现者自由设定。

通常,在JVM中使用字(word)作为数据值的基本尺寸单位。要求字的尺寸足够大,以保存byte, short, int, char, float, returnValue(Java程序猿不可用的一种JVM数据类型,用于实现Java程序中的finally子句)和reference。

而两个字足以装下long或double。普通情况下以主机平台的本地指针的尺寸为字的尺寸标准。

假设机器和系统平台是32位的,int值和全部引用(reference) 都被分配了32位内存;假设机器和系统平台是64位的,int值可能被分配了64位空间

通常int的用户并不关心int的实现,int的内存空间无论是32位还是64位,不得影响int的接口。即使系统用64位来保存int值,2147483647+1仍然会(也应该)表现为溢出(变成了最小值)。


练习4-1.:解释int类型的接口和实现的分离。


练习4-2.:编程typeSystem.primitive. IntDemo,验证溢出和i == -i。

2. boolean类型的接口和实现

计算机会做的事情只是是算术操作和逻辑操作。因而布尔表达式在if-else语句、?:操作和循环语句中被广泛使用。关系操作符如5>2、x!=y等取值得到一个boolean值,布尔操作符如p && q进行逻辑运算。

不论什么一个非0的整数值x,表达式x!=0的值为true;不论什么一个非null的引用ref,表达式ref!=null的值为true。

当人们眉开眼笑地讨论Java的布尔表达式、boolean类型时,其实讨论的是boolean接口。然而Java语言中如此重要和基础的boolean类型。并不实质性地存在。嗯,这个玩笑有点大。《JVM规范第2版》中有一节<3.3.4There Is No boolean Type>。其实JVM定义了boolean类型,可是没有提供操作boolean的指令。

《Java
虚拟机规范(Java SE 7 版)》的标题<2.3.4 boolean类型>更加严谨一些。

在JVM中。源码的boolean类型的运算被实现为JVM的int类型运算。

源码的boolean[]类型。其元素的訪问与改动使用JVM的byte类型数组的 baload 和 bastore 指令。

简单地说,boolean类型的实现。JVM定义了boolean这样的数据类型。如以"Z"或" [Z"分别表示boolean和boolean[]。也通过newarray 指令直接支持创建boolean[]。可是对boolean操作转换为int操作。1代表true、0代表false。而boolean[]视为byte数组操作。Sun的JVM实现将boolean[]元素作为8bit的值,其它JVM实现可能採用压缩形式。如一位。

int和boolean两个样例。反应了数据类型的抽象特征与事实上现的详细细节的差异。这就是将数据接口与实现加以清晰地分离的数据抽象的意义所在。


练习4-3:解释boolean类型在Java语言层面、JVM规范层面和JVM实现层面的不同,并由此解释抽象的价值。

4.1.2 类的接口

对于引用类型,不须要如同基本类型那样涉及到JVM。源码中没有对象。仅仅有引用变量和引用值。关于对象的实现參考[7.4.3堆上的对象]。类的接口与实如今[第6章封装]中详述,这里仅概要地说明。

1. 类的API

Parnas原则/接口与实现分离指在模块或方法层面,用户程序猿有意识地忽略方法的实现。而每个方法具有自己的接口。对于一个类A的用户而言,A所定义的(方法)接口唯独可以被訪问时才值得关注。很多方法——典型的如private方法,只被A自己使用,对外界而言,这些方法是否存在无关紧要也不得而知。因而在面向对象技术中,Parnas原则被推广到类层面。

类的接口指外界对象可以訪问的、类所定义的接口的集合。通常。类中声明的public、protected域,也作为类接口的一部分。

由上面的定义可知,随着客户程序与本类的关系的不同,如在或不在一个包中、是或不是本类的子类,类的接口这一集合对客户类而言会有程度上的不同。使用訪问修饰符限定类的接口,这一机制称为封装,在[第6章封装]中具体介绍。

类的接口经常称为该类的API。这是为了与Java中的接口类型相差别。一般而言private和package-private方法不是类的接口。

2. 类和类型

绝大多数情况下,能够视class为一种type。比如,在[2.2.2Java数据类型]中所给出的(数据)类型的概念,将类作为类类型。

在[2.1.1里氏替换原则]中介绍了子类(subclass)与子类型(subtype)的差别。那么,类(class)和类型(type) 又有什么差异呢?

差异表如今接口与实现的分离上。type是一个名称,它标识了类的接口。

假设一个对象可以接受X类的接口的所有操作请求(方法调用),则称对象具有X类型

正是由于Java的子类可以满足父类的接口(虽然可以改写),所以子类的对象可以同一时候具有类层次中的多个类型

类(class)则是接口和实现的综合体。类不只定义了一种类型,也定义了对象的内部状态和方法的实现,以及不是接口的方法(如private方法)。简言之。类型是类的接口,类是类型+实现。


练习4-4.:一个对象能够有多个类型。

这些类型构成了一个____,如同生物学分类。


练习4-5:不同类的对象能够具有同样的类型,这个共同的类型被称为____ 。


练习4-6:子类继承父类的接口。请讨论这一命题。


练习4-7.:解释类(class)和类型(type)的差异。

《编程导论(Java)·4.1数据抽象的含义》

时间: 2024-11-09 09:48:55

《编程导论(Java)&#183;4.1数据抽象的含义》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: