第3章 Android开发基础知识
学习指引
由于Android是采用Java语言进行开发的,因此读者必须对Java语法有一定的了解。本章正是对后期Android开发进行了一个铺垫。
重点导读
·了解基本数据类型。
·掌握数值运算和类型转换。
·熟悉流程控制。
·掌握while循环、do while循环和for循环。
·熟悉数组的创建。
3.1 基本数据类型
任何一门编程语言都有自己的基本数据类型,Java也不例外。本节将梳理Java中的基本数据类型。
3.1.1 字面值
在了解Java基本数据类型前,先了解几个计算机中的存储单位,如bit、Byte、KB、MB和GB等。
- bit:一个二进制位。
- Byte:8个二进制位为一个字节。
1KB=1024字节
1MB=1024KB
1GB=1024 MB
以上这些是计算机中的基本单位及换算关系,需要读者进行熟记。
Java中有以下8种基本数据类型。
① byte:字节型,Java中最小的数据类型,在内存中占8位(bit),即1字节,取值范围为-128~127(-27~27-1)之间,默认值为0。
② short:短整型,在内存中占16位,即两字节,取值范围为-32768~32767(-215~215-1)之间,默认值为0。
③ int:整型,用于存储整数,在内存中占32位,即4字节。取值范围为-2147483 648~2147483647 (-231~231-1)之间,默认值为0。
④ long:长整型,在内存中占64位,即8字节,取值范围-263~263-1之间,默认值为0。
⑤ float:浮点型,在内存中占32位,即4字节,用于存储带小数点的数字(与double的区别在于,float类型有效小数只有6~7位),默认值为0.0f。
⑥ double:双精度浮点型,在内存中占64位,即8字节,用于存储带小数点的数字,默认值为0.0d。
⑦ char:字符型,在内存中占16位,即两字节,用于存储单个字符,取值范围为0~65 535,默认值为空。
⑧ boolean:布尔类型,在内存中占1位,用于判断真或假。
3.1.2 取值范围查看
本小节通过一个小的实例,演示Java中几种整数类型的取值范围。新建工程,工程命名为app3后,具体操作步骤如下。
步骤1 打开新建工程,将左侧资源视图切换至res目录下的layout目录,如图3-1所示。
步骤2 双击activity_main.XML布局文件,将代码视图切换至设计视图。在设计视图中有两个界面,左侧为效果展示界面,右侧为界面布局,如图3-2所示。
步骤3 对界面进行简单布局,默认布局中会有一个文本框组件,拖动该文本框组件至合适的位置,再添加两个文本框控件,如图3-3所示。
图3-1 切换至布局文件
图3-2 切换至设计视图
步骤4 可以发现新添加的控件与系统创建控件不同,系统创建控件四周有波浪线,这个是布局约束。选中其中一个控件,其四周会出现空心圆圈,用鼠标选中一个圆圈,拖动至父布局边缘便可以形成约束,如图3-4所示。
图3-3 3个文本视图控件
图3-4 添加约束
步骤5 选中某个控件后右侧会显示出该控件的属性,如图3-5所示。
步骤6 修改3个控件的约束,修改layout_width属性为match_const,如图3-6所示。
图3-5 控件属性
图3-6 控件布局
步骤7 添加按钮控件,拖动至合适位置进行约束,如图3-7所示。
步骤8 修改按钮控件的onClick属性为doClick、修改text属性为“按钮”,如图3-8所示。
图3-7 添加按钮控件
图3-8 修改按钮属性
步骤9 切换至MainActivity.java文件,修改其中的代码。具体代码如下:
步骤10 上述程序运行后单击按钮,查看运行结果如图3-9所示。
图3-9 运行结果
3.1.3 自由落体计算
本小节通过一个实例,演示浮点数在程序中的运算。要求创建一个模块,在界面中放置一个文本框控件用于显示结果,放置一个编辑框控件用于获取用户输入的数值,以及一个按钮控件用于执行运算,具体操作步骤如下。
图3-10 创建模块
步骤1 新建一个模块,单击File→New→New Module可以创建一个新的模块,如图3-10所示。
步骤2 在打开的对话框中选择Phone & Tablet Module选项,如图3-11所示,选择完成后单击Next按钮。
步骤3 在打开的对话框中输入新模块的名称为free fall,选择开发SDK版本,如图3-12所示,设置完成后单击Next按钮。
图3-11 新建模块
图3-12 模块名称
步骤4 在打开的对话框中选择Empty Activity,即一个空的活动模板,如图3-13所示,选择完成后单击Next按钮。
步骤5 在打开的对话框中设置活动名称及布局名称,保持默认值,单击Finish按钮,如图3-14所示。
图3-13 模板选择
图3-14 创建活动名称及布局名称
步骤6 切换到新创建的模块中,设置布局,如图3-15所示。
步骤7 修改按钮的onClick属性及text属性,如图3-16所示。
图3-15 设计布局
图3-16 修改按钮属性
步骤8 切换到MainActivity.java文件中,修改主活动中的代码如下:
提示:自由落体公式为h=gt2/2,其中h为物体下落距离;g为重力加速度;t为时间。
步骤9 在编辑框中输入时间,如“20”,单击“计算结果”按钮,查看运行结果,如图3-17所示。
图3-17 运行结果
3.1.4 字面值与前后缀
1. 字面值
在Java源代码中,字面值用于表示固定的值。数值型的字面值是最常见的,字符串字面值也可以算是一种,当然还可以把特殊的null当做字面值。字面值大体上可以分为整型字面值、浮点字面值、字符和字符串字面值及特殊字面值。这里重点介绍整形字面值和浮点字面值。
1)整型字面值
从形式上看,整数的字面值可归类为整型字面值。一般情况下,字面值为int类型,但是int字面值可以赋值给byte、short、char、long、int,只要字面值在目标范围以内,Java会自动完成转换;如果试图将超出范围的字面值赋给某一类型(比如把128赋给byte类型),编译时会通不过。下面给出一些实例。
2)浮点字面值
浮点字面值可以理解为小数,默认情况下浮点数采用double类型字面值;另外,浮点字面值支持科学记数法表示。下面给出一些实例。
2. 前后缀
1)前缀
Java中为了区分不同进制数,预留了前缀。通过前缀可以告知编译器数据是什么进制及类型。
常用前缀举例如下。
(1)0x:十六进制表示法。
0x123456789abcdef:十六进制数。
(2)0:八进制表示法。
(3)\u:char类型十六进制表示法。
2)后缀
为了强调数据类型,Java中还提供了后缀。使用后缀可以告知编译器数据的类型。
常用的几种后缀如下。
- L:代表long数据类型。
- F:代表float数据类型。
- D:代表double数据类型。
例如:
3.2 数据运算
数据运算是对数据进行处理的基础,需要遵循某种运算规则,其包括算数运算、逻辑运算及关系运算规则。
3.2.1 数据运算规则
1. 常用运算举例
Java基本数据类型的数据运算中,运算结果与参与运算的数据类型中精度最高的保持一致。例如:
- 3/2,整数3除以整数2的运算结果1还是整数类型。
- 3D/2,运算结果是double 1.5。
- 1/2/4D,运算结果是double 0。运算时从左向右,其运算结果是0,因为1/2的结果是整数0,如果想要得到正确结果,需要将首次运算1/2的其中一项转换成浮点型。
Byte、short、char 3种整数类型运算时,会先自动转换为int类型。
2. 整数运算中的溢出
int、long有溢出,而byte、short没有,因为byte、short类型数据在运算时要先转换成int类型。
3. 浮点数运算不精确
以上这点需要了解,遇到需要精度较高的情况时要避免运算不精确。
4. 浮点数的特殊值
- Infinity:无穷大。
- NaN:Not a Number,不是一个数字。
3.2.2 鹊桥会
本小节通过“鹊桥会”一个经典实例,演示基本数据类型在实际中的应用。
已知牛郎星距离织女星约16.4光年,光速为299 792 458m/s,一只喜鹊身长0.46m,要求计算牛郎与织女相会需要多少只喜鹊。
创建新的模块,在模块中设置一个文本框控件和一个按钮控件,通过计算输出结果,具体操作步骤如下。
步骤1 新建模块并设置模块名称为bridge,界面布局如图3-18所示。
步骤2 修改主活动中的代码。具体代码如下:
步骤3 上述程序运行后单击“计算”按钮,查看运行结果,如图3-19所示。这里运算出来的喜鹊数量是浮点数,但每只喜鹊是一个独立整体,因此喜鹊数量不可能存在浮点数,这个留在下一节讲解。
图3-18 界面布局
图3-19 运行结果
3.2.3 类型转换与运算符
在数据运算中,两个类型不匹配的数据运算过程中会涉及类型转换(其又分为自动类型转换与强制类型转换两种),而在运算过程中自然还需要各种运算符。下面对类型转换和运算符分别进行讲解。
1. 类型转换
1)自动转换
从低精度转换为高精度或数据类型从小转换到大都可以自动转换。例如,byte→short→int→long→float→double这些类型都可以自动转换。
2)强制转换
高精度转换为低精度可以强制转换。例如:
浮点数转换为整数,舍弃小数。例如,上一节中的喜鹊数量要得到一个整数便需要强制转换(喜鹊数量强制转换为long类型可避免数据不准确),修改代码为long n=long(d/0.46+0.9);。注意后面的运算要括起来,否则可能导致只对前面的数据进行强制转换。
2. 运算符
Java中的常用运算符见表3-1。
表3-1 常用运算符
赋值运算符“=”可以与其他运算符结合使用。例如:
- +=(加等于),表示将结果计算完成后再赋值。
- *=(乘等于),表示先进行相乘运算,再进行赋值。
3.2.4 是否为闰年
经典案例“闰年判断”会涉及大量的运算,本小节通过该案例熟悉运算符的操作。闰年的判断条件是能被4整除但不能被100整除,或者是能被400整除。
创建一个新模块,在模块中放置一个编辑框控件用于获取用户输入信息,再放置一个按钮控件,以实现输入年份后单击该按钮便提示该年份是否为闰年,具体操作步骤如下。
步骤1 新建模块并命名为leap year,界面布局如图3-20所示。
图3-20 界面布局
步骤2 修改编辑框控件的hint属性,给出用户提示信息,如“请输入年份”,如图3-21所示。
步骤3 修改按钮的onClick属性和text属性,如图3-22所示。
图3-21 编辑框属性
图3-22 按钮属性
步骤4 修改主活动中的代码。具体代码如下:
步骤5 运行上述程序后输入相应的年份进行测试,查看运行结果,如图3-23所示。
图3-23 运行结果
提示:修改上述步骤4闰年判断中的条件语句,使用一条语句完成判断。具体代码如下:
3.2.5 位运算
Java中的位运算是将需要运算的数据类型先转换成二进制,再进行相应的位运算,本质是二进制运算。位运算符包括按位与、按位或、按位异或、取反、左移及右移。
- &:按位与运算符,两位同时为1则结果为1。
- |:按位或运算符,两位同时为0则结果为0。
- ^:按位异或运算符,两位相同为0,不同为1,对同一个数字异或两次得到同值。
- ~:取反运算符,1与0互换。
- >>:有符号算数右移运算符,要用原来的符号位填充操作数右移的空位。
- >>>:无符号算数右移运算符,高位全部补0。
- <<:左移运算符,左移后全部补0(左移不涉及符号位,因此全部补0),不区分逻辑与算数运算。
注意:右移位相当于除以2,左移位相当于乘以2。
本小节通过一个案例熟悉位运算,拆分整数成4个byte类型数据。新建一个模块并依次创建一个编辑框用于用户输入整数数据、一个文本框控件用于显示运算结果及一个按钮控件用于提交运算,具体操作步骤如下。
步骤1 新建模块并命名为split,界面布局如图3-24所示。
步骤2 修改按钮的onClick属性和text属性,如图3-25所示。
图3-24 界面布局
图3-25 按钮属性
步骤3 修改主活动中的代码。具体代码如下:
步骤4 运行上述程序,查看运行结果,如图3-26所示。
图3-26 运行结果
3.3 流程控制
程序的执行顺序是依次往下的,但是通过流程控制可以改变程序的运行顺序。由于有了流程控制,程序运行才变得多变,进而解决更加复杂的问题。
3.3.1 简单流程控制
简单判断语句分为if、if…else、if…else if…else及它们之间的嵌套。
(1)生活中经常需要先做判断,然后才决定是否要做某件事情。例如,如果下雨,则在家打游戏。对于这种需要先判断条件,条件满足后才执行的情况,就可以使用if条件判断语句实现。
语法格式:
其执行流程示意图,如图3-27所示。
(2)if…else语句的操作比if语句多了一步,当条件成立时,则执行if部分的代码块;如果条件不成立,则执行else部分的代码块。例如,如果下雨,则在家打游戏;否则,出去逛街。
语法格式:
其执行流程示意图,如图3-28所示。
图3-27 if执行流程
图3-28 if else执行流程
(3)多重if语句——if…else if…else语句在条件1不满足的情况下,会进行条件2的判断;当前面的条件均不成立时,才会执行else内的代码块。例如,如果阴天,则写作业;如果下雨,则在家打游戏;否则,去逛街。
语法格式:
其执行流程示意图,如图3-29所示。
(4)嵌套if语句只有当外层if的条件成立时,才会判断内层if的条件。例如,某活动计划的安排:如果今天是工作日,则去上班;如果今天是周末,且天气晴朗就进行户外活动,否则在室内活动。
语法格式:
其执行流程示意图,如图3-30所示。
图3-29 多重if执行流程
图3-30 if嵌套执行流程
3.3.2 个人所得税
通过用户输入工资,判断个人应交税费,这个项目可以很好地利用简单流程控制来实现。个人所得税参考表3-2,其仅用于学术研究,内容不作为实际参考。
表3-2 个人所得税参考表
新建一个模块,在模块中放置一个编辑框控件、一个文本框控件和一个按钮控件,具体操作步骤如下:
步骤1 新建模块命名为revenue,布局控件如图3-31所示,并修改按钮属性。
步骤2 定义两个变量,r为税率,k为速算扣除数。具体代码如下:
图3-31 界面布局
步骤3 工资低于3500元,返回0,因为没有达到扣税标准。具体代码如下:
步骤4 工资高于3500元,扣除不纳税部分3500元后,计算税率(计算公式为应纳税部分×税率-速算扣除数)。具体代码如下:
步骤5 修改主活动中的代码。具体代码如下:
步骤6 运行上述程序后,输入工资,查看运行结果,如图3-32所示。
图3-32 运行结果
3.3.3 switch case
switch case语句是多路选择语句,它可以与if…else if相互转换,但是如果判断条件比较多时,switch case语句效率要高一些。
语法格式:
switch语句由一个控制表达式和多个case条件组成,switch控制表达式支持的类型有byte、short、char、int、enum(Java 5)和string(Java 7)。switch语句中有一个default关键字,在当前switch找不到匹配的case条件时执行其语句,default并不是必需的。
一旦case条件匹配,就会顺序执行后面的程序代码,而不管后面的case条件是否匹配,直到遇到break。break在switch语句中用于结束当前流程,以下程序中存在一个忘记编写break的“陷阱”。
上述程序运行结束后,结果为a=3。虽然i=1进入了第一个case,但是由于没有break,因此一直顺序执行到case 3将a重新赋值为3。可见,在使用switch语句时一定不能忘记添加break。
3.3.4 最大天数
本小节通过“最大天数”项目熟悉switch case语句的使用,该项目实现由用户输入一个某年某月,得出该月的天数。
创建新的模块,设置两个编辑框控件、一个文本框控件和一个按钮控件,具体操作步骤如下。
步骤1 新建模块并命名为MAXday,界面布局如图3-33所示。
图3-33 界面布局
步骤2 创建函数runNian()用于判断是否为闰年,该函数返回值为布尔类型。
步骤3 修改主活动中的代码。具体代码如下:
步骤4 运行上述程序,输入年份与月份,查看运行结果,如图3-34所示。
图3-34 运行结果
3.4 循环
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。一组被重复执行的语句称为循环体。能否继续重复,由循环的终止条件决定。
3.4.1 while循环
While循环是Java中的一种基本循环模式。当满足条件时,开始进入while循环;进入循环后,当条件不满足时,跳出循环。
语法格式:
下面通过一个实例——求n的阶乘,演示如何使用while循环。创建新模块并设置一个编辑框用于输入n的值、一个文本框用于显示计算结果和一个按钮用于提交信息,具体操作步骤如下。
步骤1 新建模块并命名为factorial,界面布局如图3-35所示。
图3-35 布局界面
步骤2 修改主活动中的代码。具体代码如下:
步骤3 运行上述程序,输入相应数据并单击“提交”按钮,运行结果如图3-36所示。
图3-36 运行结果
3.4.2 do while循环
do while循环与while循环类似,唯一的不同在于:do while循环至少需要执行一次,而while循环则不一定。
语法格式:
下面通过一个实例——计算π的值,演示如何使用do while循环。计算π的公式如下:
π/4=1/1-1/3+1/5-1/7+1/9…
创建一个模块并命名为pai,设置一个编辑框控件用于输入结束数据,再设置一个文本框控件和一个按钮控件,以实现单击按钮便将计算结果显示在文本框控件内。主活动代码如下:
运行上述程序,输入一个数值,其范围越大则π值越精确,查看运行结果,如图3-37所示。
图3-37 运行结果
3.4.3 for循环
for循环是一种更加接近人类语言的循环模式,它用了3个表达式,而且每个表达式都可以省略。
语法格式:
下面通过一个实例——判断一个数是不是水仙花数,演示如何使用for循环。水仙花数也被称为超完全数字不变数、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数,其是指一个3位数每位数字的3次幂之和等于它本身(例如:13+53+33=153)。
创建一个模块并命名为narcissistic,设置一个编辑框控件用于接收用户输入的数值、一个文本框控件用于输出结果和一个按钮控件用于开始程序运算。拆出一个整数(如736)的个位、十位、百位等的具体方法如下:
主活动中的具体的实现代码如下:
运行上述程序,输入999,计算该3位数范围内的所有水仙花数,运行结果如图3-38所示。本实例使用了Math.pow()方法,该方法是Java类库自带方法,读者只要会用即可。
图3-38 运行结果
3.4.4 循环嵌套
循环嵌套是程序中常用的一种方法。在一个循环体内部还包含另一个或多个循环语句,这样的循环被称为循环嵌套。下面通过一个实例,演示循环嵌套。“百钱买百鸡”实例——小鸡1元/只,母鸡3元/只,公鸡5元/只,要求用100元购买100只鸡有多少种组合方式。
新建一个模块并命名为chicken,在界面中设置一个文本框控件用于显示结果、一个按钮控件用于开始计算。核心代码如下:
完整代码可参考第3章的chicken模块,运行结果如图3-39所示。
图3-39 运行结果
3.5 数组
数组用于存储具有统一类型的一组数据,一旦数组的长度确定,将不能改变。数组是一个复合型数据类型,其在实际编程中会被大量使用。
3.5.1 数组的创建
数组的创建可以分为3种情况:第一种是使用new关键字创建;第二种是直接给定一个数组;第三种是通过new关键字创建一个给定元素的数组。
第一种:int[]a=new int[5];,新建一个int类型的数组,数组长度为6,数组创建出来后使用0填充其各元素。
第二种:int[]a={24,12,58,77,2,18};,创建一个int类型的数组,其包括{}中的6个元素,数组的长度为6。
第三种:int[]a=new int[]{12,35,55};,创建一个int类型的数组,其包括3个元素,数组的长度为3。
数组的内部可以存储基本数据类型的数据。例如:
- 0,12,3——整数数据类型。
- 3.14,0.123——浮点数数据类型。
- false,true3——布尔数据类型。
- 数组在创建后,不同数据类型会有不同的初始值。具体如下:
- int类型定义的数组,其初始化默认值为0。
- String类型定义的数组,其默认值为null。
- char类型定义的数组,其默认值为0对应的字符。
- double类型定义的数组,其默认值为0.0。
- float类型定义的数组,其默认值为0.0。
- boolen类型定义的数组,其默认为false。
3.5.2 数组的使用
创建完数组便可以使用数组了。数组的存取都是通过数组下标来实现的,需要注意的是,Java中的数组下标是从0开始的。
给数组中某个位置的元素赋值,例如:
将数组中某个位置的元素赋值给一个变量,例如:
使用数组需要注意的是,数组越界的问题,数组越界会导致程序出错。数组有一个长度属性length,在数组存取时可以先通过length属性获取数组长度,再对数组进行操作。例如,遍历数组中的所有元素,具体代码如下:
3.5.3 双色球
本小节通过“双色球”实例熟悉数组的存取。新建一个模块并命名为Double Ball,该项目中需要创建5个数组:创建一个数组用于存放红色球编号,同时创建一个等长的boolean型数组用于判断红色球的选取状态,再创建一个数组用于存放蓝色球编号,同时创建一个等长的boolean型数组用于判断蓝色球的选取状态,最后创建一个数组用于存放取出的球。这里选用的是“33+1”双色球。
完整代码可参阅第3章的Double Ball模块,其中核心代码如下:
运行上述程序,单击“机选(6+1)”按钮,查看运行结果,如图3-40所示。
图3-40 运行结果
3.5.4 排序
在实际开发中排序算法的使用非常频繁,了解排序算法对于编程思想的构建是非常有帮助的。本小节将介绍两种基本排序算法——插入排序算法和冒泡排序算法,通过这两种排序算法,读者能够更加深入理解数组的存储及使用。
新建一个模块并命名为sort,设置两个文本框控件,第一个文本框控件用于显示随机生成的数组元素,第二个文本框控件用于显示排序后的数组元素,再设置两个按钮控件,分别进行插入排序和冒泡排序操作。具体代码如下:
运行上述程序,单击相应的排序按钮,查看运行结果,如图3-41所示。
图3-41 运行结果
3.5.5 二分查找
通过学习前面的排序算法,相信读者对数组和排序都有了一定的了解。有了排序的基础,读者才能更好地进行本小节的二分查找学习。二分查找也是编程进化中的一种思想。
新建一个模块并命名为binary search,设置两个文本框控件,一个用于显示随机生成的数组,一个用于显示找到元素的下标位置,再设置一个编辑框控件用于获取用户输入的整数,最后设置两个按钮控件,一个用于随机生成数组,一个用于开始查找。具体代码如下:
运行上述程序,单击“生成”按钮。随机生成数组,然后输入需要查找的元素,单击“查找”按钮,运行结果如图3-42所示。
图3-42 运行结果
3.6 就业面试技巧与解析
本章主要讲解了Java开发基础,由于Android采用Java语言进行开发,因此Java语言掌握得好坏也能从侧面反映出Android开发者的功底。面试中面试官会问及Java基础问题,尤其是各个运算符的优先级、逻辑运算等。
3.6.1 面试技巧与解析(一)
面试官:如果忘记运算符优先级,如何保证程序运算结果的正确性?
应聘者:如果忘记运算符优先级,最简的办法是将长运算拆分成单独运算,再最后组合,当然也可以使用括号将不同的运算括起来以保证运算优先层级清晰。
3.6.2 面试技巧与解析(二)
面试官:while、do while和for 3种不同的循环是否可以混用?在什么情况下使用何种循环?
应聘者:在编程原理上,这3种循环是可以进行相互转换的。while循环一般用于不清楚何时结束的循环,do while循环则用于至少需要执行一次的循环,而for循环是使用较多的循环,它更加符合人类语言规范。