第一部分 编程基础与二进制~~第1章 编程基础

151 阅读9分钟

我们先来简单介绍何谓编程,以及编出来的程序大概是什么样子。

计算机是个机器,这个机器主要由CPU、内存、硬盘和输入/输出设备组成。计算机上跑着操作系统,如Windows或Linux,操作系统上运行着各种应用程序,如Word、QQ等。

操作系统将时间分成很多细小的时间片,一个时间片给一个程序用,另一个时间片给另一个程序用,并频繁地在程序间切换。不过,在应用程序看来,整个机器资源好像都归它使用,操作系统给它制造了这种假象。对程序员而言,编写程序时基本不用考虑其他应用程序,做好自己的事就可以了。

应用程序看上去能做很多事情,能读写文档、能播放音乐、能聊天、能玩游戏、能下围棋等,但本质上,计算机只会执行预先写好的指令而已,这些指令也只是操作数据或设备。所谓程序,基本上就是告诉计算机要操作的数据和执行的指令序列,即对什么数据做什么操作,比如:

  1. 读文档,就是将数据从磁盘加载到内存,然后输出到显示器上;
  2. 写文档,就是将数据从内存写回磁盘;
  3. 播放音乐,就是将音乐的数据加载到内存,然后写到声卡上;
  4. 聊天,就是从键盘接收聊天数据,放到内存,然后传给网卡,通过网卡传给另一个人的网卡,再从网卡传到内存,显示在显示器上。

基本上,所有数据都需要放到内存进行处理,程序的很大一部分工作就是操作在内存中的数据。那具体如何表示和操作数据呢?本章介绍一些基础知识,具体分为7个小节。

数据在计算机内部都是二进制表示的,不方便操作,为了方便操作数据,高级语言引入了数据类型变量的概念,这两个概念我们在1.1节介绍。

表示了数据后,1.2节介绍能对数据进行的第一个操作:赋值。

数据有了初始化值之后,1.3节介绍可以对数据进行的一些基本运算,计算甲之所以称为 "计算"机,是因为最初发明它的主要目的也是运算。

为了编写有实用功能的程序,只进行基本运算是远远不够的,至少需要对操作的过程进行流程控制。流程控制有两种:一种是条件执行;另外一种是循环。我们分别在1.4节和1.5节介绍。

为了减少重复代码和分解复杂操作,计算机程序引入了函数和子程序的概念,我们分别在1.6节和1.7节介绍函数的用法和函数调用的基本原理。

1.1 数据类型和变量

数据类型用于对数据归类,以便于理解和操作。对Java语言而言,有如下基本数据类型。

  • 整数类型:有4种整型byte/short/int/long, 分别有不同的取值范围;
  • 小数类型:有两种类型float/double, 有不同的取值范围和精度;
  • 字符类型:char, 表示单个字符;
  • 真假类型:boolean, 表示真假。

基本数据类型都有对应的数组类型,数组表示固定长度的同种类型的多条记录,这些数据在内存中连续存放。比如,一个自然数可以用一个整数类型数据表示,100个连续的自然数可以用一个成都为100的整数数组表示。一个字符可以用一个char类型数据表示,一段文字可以用一个char数组表示。

Java是面向对象的语言,除了基本数据类型,其他都是对象类型。对象到底是什么呢?简单地说,对象是由基本数据类型、数组和其他对象组合而成的一个东西,以方便对其整体进行操作。比如,一个学生对象,可以由如下信息组成。

  • 姓名:一个字符数组;
  • 年龄:一个整数;
  • 入学分数:一个小数。

日期在Java中也是一个对象,内部表示为整型long。

世界万物都是由元素周期表中的基本元素组成的,基本数据类型就相当于化学中的基本元素,而对象就相当于世界万物。

为了操作数据,需要把数据存放到内存中。所谓内存在程序看来就是一块有地址编号的连续的空间,数据放到内存中的某个位置后,为了方便地找到和操作这个数据,需要给这个位置起一个名字。编程语言通过 变量 这个概念来表示这个过程。

声明一个变量,比如int a, 其实就是在内存中分配了一块空间,这块空间存放init数据类型,a指向这块内存空间所在的位置,通过对a操作即可操作a指向的内存空间,比如 a=5这个操作即可将a指向的内存空间的值改为5。

之所以叫 “变” 量,是因为它表示的是内存中的位置,这个位置存放的值是可以变化的。

虽然变量的值是可以变化的,但变量的名字是不变的,这个名字应该代表程序员心目中这块内存空间的意义,这个意义应该是不变的。比如,变量int second表示时钟秒数,在不同时间可以被赋予不同的值,但它表示的始终是时钟秒数。之所以说 应该,是因为这不是必需的,如果一定要为一个名为age的变量赋予身高的值,计算机也拿你没办法。

重要的话再说一遍!变量就是给数据起名字,方便找不同的数据,它的的值可以变,但含义不应变。 再比如说一个合同,可以有4个变量:

  • first_party: 含义是甲方;
  • second_party: 含义是乙方;
  • contract_body: 含义是合同内容;
  • contract_sign_date: 含义是合同签署日期。

这些变量表示的含义是确定的,但对不同的合同,它们的值是不同的。初学编程的人经常使用像a、b、c、hehe、haha这种无意义的名字。在此建议为变量起一个有意义的名字吧!通过声明变量,每个变量赋予一个数据类型和一个有意义的名字,我们就告诉了计算机要操作的数据。

有了数据,如何对数据进行操作呢?我们先来看对数据能做的第一个操作:赋值。

1.2 赋值

声明变量之后,就在内存分配了一块位置,但这个位置的内容是未知的,赋值就是把这块位置的内容设置为一个确定的值。Java中基本类型、数组、对象的赋值有明显不同,本节介绍基本类型和数组的赋值,对象的赋值第3章再介绍。

1.2.1 基本类型

(1) 整数类型 整数类型有byte、short、int和long,分别占1、2、4、8个字节,

1.3 基本运算

1.4 条件执行

流程控制中最基本的就是条件执行,也就是说,一些操作只能在某些条件满足的情况下才能执行,在一些条件下执行某种操作,在另外一些条件下执行另外的操作。这与交通控制中的红灯停、绿灯行条件执行时类似的。我们先来看Java中表达条件执行的语法,然后介绍其实现原理。

1.4.1 语法和陷阱

Java中表达条件执行的基本语法是if语句,它的语法是:

if(条件语句){
    代码块
}

if(条件语法) 代码;
表达的含义也非常简单,只在条件语句为真的情况下,才执行后面的代码,为假就不执行了。具体来说,条件语句必须为布尔值,可以是一个直接的布尔变量,也可以是变量运算后的结果。我们在1.3节介绍过,比较运算和逻辑运算的结果都是布尔值,所以可作为条件语句。条件语句为true,则执行括号{}中的代码,如果后面没有括号,则执行后面第一个分号(;)前的代码。

1.5 循环

1.6 函数的用法

1.6.3 小结

函数是计算机程序的一种重要结构,通过函数来减少重复代码、分解复杂操作是计算机程序的一种重要思维方式。 本节我们介绍了函数的基础概念,以及关于参数传递、返回值、重载、递归方面的一些细节。

在Java中,函数还有大量的修饰符,如public、private、static、final、synchronized、abstract等,本节假定函数的修饰符都是public static,在后续章节中,我们再介绍这些修饰符。函数中还可以声明异常,我们也到第6章再介绍。

1.7 函数调用的基本原理

在介绍递归函数的时候,我们看到了一个系统错误:java.lang.StackOverflowError,理解这个错误,需要理解函数调用的实现机制。下面,我们先来了解一个重要的概念:栈,然后再通过一些例子来仔细分析函数调用的过程。

1.7.1 栈的概念

我们之前谈过程序执行的基本原理:CPU有一个指令指示器,指向下一条要执行的指令,要么顺序执行,要么进行跳转(条件跳转或无条件跳转)。

基本上,这依然是成立的,程序从main函数开始顺序执行,函数调用可以看作一个