[置顶] Java核心技术(二) —— Java的基本程序设计结构

时间:2023-02-16 11:34:04

本文主要讲述程序设计相关的基本概念在Java中的实现方式,涉及的内容很多很细,包括注释、数据类型、变量、运算符、字符串、输入输出、控制流、大数值和数组。

1、基本认知

(1)Java对大小写敏感
(2)源代码的文件名必须与公共类的名字相同,并以.java作为扩展名
(3)源代码文件经过编译得到一个包含这个类的字节码的文件,并将其自动地命名为同名文件,只不过扩展名为.class,并与源文件存储在同一个目录下。
(4)运行编译后的程序时,java虚拟机将从制定类中的main方法(方法即函数)开始执行,因此为了代码能够执行,在类的源文件中必须包含一个main方法,且必须声明为public,static的。
(5).用来调用方法。

2、注释

注释并不会出现在可执行程序中,因而不必担心可执行代码膨胀。
(1)//行注释
(2)/加一星号开头,一星号加/结尾,进行段注释
(3)/加两星号开头,一星号加/结尾,可以自动生成文档。注意每行以星号开头,如
[置顶]        Java核心技术(二) —— Java的基本程序设计结构

3、数据类型

Java为强类型语言,即必须为每一个变量声明一种类型。
Java包含八种基本类型,四种整型、两种浮点类型、一种字符类型、一种布尔类型。

3.1 整型

[置顶]        Java核心技术(二) —— Java的基本程序设计结构
(1)注意Java中没有任何无符号类型(unsigned)
(2)加前缀0b可以用来写二进制数,如0b1001就是9。也可以为数字字面量加下划线,如1_000_000表示一百万,当然这里的下划线只是为了人们读方面,java编译器会去除这些下划线。

3.2 浮点类型

[置顶]        Java核心技术(二) —— Java的基本程序设计结构
(1)一般来说,很少使用float类型,除了需要快速处理单精度数据、需要存储大量数据时。
(2)float类型数值有一个后缀F,如3.14F,没有的话默认为double型。
(3)注意,有三个特殊的浮点数值表示:POSITIVE_INFINITY、NEGATIVE_INFINITY和NaN。注意所有非数值被认为是不相同的,不能进行if判断等等,如if(x == Double.NaN)是错的。
(4)还需注意的一点是,浮点数值不适用于禁止出现舍入误差的金融计算中,如System.out.println(2.0-1,1)将打印出0.8999999999999,而不是期望的0.9。显然这是由于浮点数值采用二进制系统表示导致的。如果需要数值计算中不含有任何舍入误差,应该使用后面介绍的BigDecimal类。

3.3 Char类型

char类型用于表示单个字符,通常用来表示字符常量。
(1)同样,’A’表示字符常量,而”A”表示包含字符A的字符串。
(2)\u时转义序列符,可以用来表示Unicode代码单元的编码,或者一些特殊的字符,常用的特殊转义序列符
[置顶]        Java核心技术(二) —— Java的基本程序设计结构
(3)在Java中,插入类型用UTF-16编码描述一个代码单元,最好不要使用char类型,最好将需要处理的字符串用抽象数据类型表示

3.4 布尔类型

即false和true。
(1)注意,区别于C++等,这里整型值和布尔值之间不能进行相互转换。

4、变量

在Java中,每一个变量属于一种类型。
(1)变量名必须是一个以字母开头的包含字符或数字的序列
(2)大小写敏感,长度无限制
(3)虽然可以一行中声明多个变量,但建议逐一声明每一个变量

4.1 变量初始化

区别于C++,java中不区分变量的声明和定义。声明一个变量后。必须用赋值语句对变量进行显示初始化,千万不可使用未被初始化的变量。

4.2 常量

(1)java中利用关键字final表示常量,即这个变量只能被赋值一次,一旦赋值,不可再改。习惯上,常量名使用全大写。注意不使用const。
(2)如果一个常量需要在一个类中的多个方法中使用,即类常量,可以使用关键字static final进行设置。

5、运算符

(1)当参与/运算的两个操作数都是整数时,表示整数除法,否则表示浮点除法。注意,整数除以0会产生异常,而浮点数除以0会得到无穷大或者NaN。
(2)浮点型数值在不同平台运算涉及到精度的截断或者扩展,很难达到可移植性。对于使用strictfp关键字标记的方法,要求方法中的所有指令都必须使用严格的浮点计算。

5.1 自增、自减运算符

当自增自减运算符用到表达式中时,后缀形式(即++,–在变量后)在自增自减后还是使用变量原来的值,而前缀形式则是自增自减后就用变化后的这个值餐与运算。
[置顶]        Java核心技术(二) —— Java的基本程序设计结构

5.2 关系运算符与布尔运算符

(1)关系运算符得到的结果为false或者true
(2)与&&,或||,采用短路逻辑,即前一个操作数已经可确定表达式值,就不计算后一个。
(3)三元运算符

condition ? expression1 : expression2

即当condition为真时计算表达式1,否则计算2
例可用

x < y ? x : y

返回x与y中较小的那个值

5.3 位运算符

(1)
[置顶]        Java核心技术(二) —— Java的基本程序设计结构
(2)>>和<<进行右移或左移,>>>将用0填充高位,>>用符号为填充高位,没有<<<运算符
(3)对移位运算符右侧的参数需要进行模32的运算,除非左边的操作数是long型,那么此时进行模64运算即可,如1<<35和1<<3都表示8。

5.4 数学函数与常量

Math类中包含了许多数学函数。
(1)Java中没有幂运算,需要借用Math.power(x,a)方法
(2)Math的导入只要在源文件的顶部加上这行代码

import static java.lang.Math.*;

5.5 数值类型之间的转换

以下为数值类型之间的合法转换方向
[置顶]        Java核心技术(二) —— Java的基本程序设计结构
对于不同类型的两个操作数进行运算时,会自动转换为同一种类型,转换方式参考上图方向,让两者保持最远的那个类型。

5.6 强制类型转换

当需要实现上图不存在的转换关系时,即需要进行强制类型转换,当然会造成信息丢失。通过在待转换的变量名前加(目标类型)进行,如(int) x。
注意,不要在布尔类型和其他任意数值类型之间进行强制类型转换,入药的情况可以适用条件表达式

b ? 1 : 0

5.7 括号与运算符级别

[置顶]        Java核心技术(二) —— Java的基本程序设计结构

5.8 枚举类型

[置顶]        Java核心技术(二) —— Java的基本程序设计结构

6、字符串

每个用双引号括起来的字符串都是String类的一个实例

6.1 子串

String类的substring方法可以从一个较大的字符串中提取出一个子串。
substring中从0开始计数,s.substring(a,b)表示提取字符串s的第a个字符到第b个(不包含第b个)。

6.2 拼接

循序使用+号进行连接两个字符串,当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串。

6.3 不可变字符串

String类没有提供类似于C++中那种修改字符串的方法,如将”Hello”修改为”Help!”只能使用提取加拼接来实现替换。
因此,Java文档中将String类对象称为不可变字符串。

6.4 检测字符串是否相等

使用equals方法

s.equals(t)

注意s和t可以是字符串变量也可以是字符串常量。
equalsIgnoreCase方法是不区分大小写检测
切忌使用==检测字符串是否相等。

6.5 空串和Null串

空串“”是一个Java对象,有自己的串长度(0)和内容(空)。
还有一种特殊的String值,null,表示目前没有任何对象与该变量关联。
常用下属语句检查字符串既不是Null也不是空串

if (str != null && str.length() != 0)

6.6 构建字符串

采用前面介绍的字符串拼接大方是构建字符串,效率较低,因为每次拼接都会构建一个新的string对象,耗时浪费空间,可使用StringBuilder类。
[置顶]        Java核心技术(二) —— Java的基本程序设计结构

7、输入输出

7.1 读取输入

想通过控制台进行输入,首先需要构造一个Scanner对象,并与标准输入流System.in关联

Scanner in = new Scanner(System.in);

现在才可以使用Scanner类的各种方法实现输入操作,如

String name = in.nextLine();

用来输入一行。
Scanner类定义在java.util包中,当使用的类不是定义在基本的java.lang包中时,需要使用import指示字将相应的包加载进来,即在程序的最开始添加

import java.util.*;

另外需要注意的是,Scanner类不适用于从控制台读取密码,应使用Console类。

7.2 格式化输出

较输入简单很多,直接使用System.out.print(x)将数值x输出到标准输出流(控制台窗口)上。此命令将以x对应的数据类型所允许的最大非零数字位数打印输出x。
(1)System.out.prinf(“%8.2f”,x);
即用8个字符的宽度和小数点后2个字符的精度打印x,例对于10000.0/3.0,将输出 3333.33,即一个空格和七个字符。
(2)printf也可也使用多个参数
[置顶]        Java核心技术(二) —— Java的基本程序设计结构
关于转换符的释义见
[置顶]        Java核心技术(二) —— Java的基本程序设计结构

7.3 文件输入与输出

类似于输入,要对文件进行读取,需要用一个File对象构造一个Scanner对象,如

Scanner in = new Scanner(paths.get(“myfile.txt”));

当然,如果文件名中包含符号\,需要在每个\钱再加一个额外的\避免歧义。
注意,当用一个不存在的文件构造一个Scanner或者不能被创建的文件名构造一个PrintWriter时,会产生严重异常,如果知道有可能出现这种异常,需提前在main方法中用throws字句标记。

8、控制流程

即我们要介绍条件语句和循环语句。Java没有goto语句,有break语句。

8.1 块作用域

不可以在嵌套的两个块中声明同名的变量。,区别于C++。

8.2 条件语句

if (condition) statement

以及

if (condition) statement1 else statement2

else永远跟最邻近的if构成一组。

8.3 循环语句

while (condition) statement

下述语句可以实现循环体至少被执行一次

do statement while (condition)

8.4 确定循环

即常用的for循环,注意在循环中,检测两个浮点数是否相等需要格外小心

for (int i = 0; i != 10; i += 0.1) …

可能永远都不会终结。由于舍入误差的存在,最终可能得不到精确值,上述程序中x将从9.99999999999998直接跳到10.09999999999998。
同样的,for语句第一部分中声明的变量,其作用域就为for循环的整个循环体。

8.5 多重选择

switch (choice)
{
case 1:
...
break;
case 2:
...
break;
default:
// bad input
...
break;
}

注意,如果在case分支语句的末尾没有break语句就会接着执行下一个case分支语句,即触发多个case分支,相当危险,一定要避免。
为了避免此危险,建议编译代码时加上-Xlint:fallthrough选项。如此一来,如果某个分支最后缺少一个break语句,编译器就会给出警告。
case标签可以是
(1)类型为char、byte、short或者int的常量表达式
(2)枚举常量
(3)字符串字面量
注意,在switch语句中使用枚举常量时,不必在每个case钟志明枚举名,可以由switch的表达式值确定。

8.6 中断控制流程语句

(1)前面使用的break为普通用法,还有一种带标签的break用法,如
[置顶]        Java核心技术(二) —— Java的基本程序设计结构
当满足condition时,通过执行带标签的break跳转到标签label冒号后的语句块的末尾,其实类似于C++的goto命令。
(2)与break不同,continue中断正常的控制流程,是将控制转移到最内层循环的首部。对于for循环,则跳到for循环的更新部分,即第三部分。

9、大数值

有时基本的整数和浮点数的精度不能满足需求,可以适用java.math包中的两个类:BigInteger和BigDecimal,分别可以实现任意精度的整数运算和任意精度的浮点数运算。
可以通过这两个类中的valueOf()方法将普通的数值转换为大数值,但对于步数值之间的算术运算,不能再使用+,*等,需要使用类中的add和multiple方法。

10、数组

数组是一种数据结构,用来存储同一类型值的集合,通过一个整型下标来访问数组中的每一个值。
(1)声明方法

int[] a;

(2)初始化,使用new运算符创建数组

int[] a = new int[100];

从而创建了一个可以存储一百个整数的数组。
创建一个数字数组时,所有元素初始化为0,布尔数组的元素初始化为false,对象数组的元素初始化为null。
(3)注意数组的一个元素为a(0)
(4)数组一旦创建,不可改变大小。如需扩展数组大小,应该是用另一种数据结构——数组列表,后面会讲。

10.1 for each 循环

可以快捷依次处理数组中的每个元素而不需要使用下标值。基本语法为

for (variable : collection) statement

定义的变量用于暂存集合中的每一个元素,并执行后续的语句。注意集合表达式collection必须是一个数组,或一个实现了Iterable接口的类对象,如ArrayList(数组列表)。

10.2 数组初始化以及匿名数组

(1)Java提供了一种创建数组并同时赋初值的简化书写方式

int[] smallPrimes = {2, 3, 5, 7, 11, 13};

即不需要调用new。
(2)还允许初始化一个匿名的数组

new int[] {2, 3, 5, 7, 11, 13}

10.3 数组拷贝

Java允许将一个数组变量拷贝给另一个数组变量,此时两个变量将引用同一个数组。这里的拷贝即用赋值符号=实现。

10.4 数组排序

需要对数值型数组进行排序时,可以适用Arrays类中的sort方法。

10.5 多维数组

多维数组将使用多个下标访问数组元素,适用于表示表格或者更加复杂的排列形式。例如声明一个二维数组

double[][] a;

同样,在初始化之前不可使用

a = new double[b][c];

同样可以使用简便方式初始化

int[][] a = {{1,2,3}, {4,5,6}, {7,8,9}};

注意对于二维数组,for each语句不能自动处理其中每一个元素,其是按照行进行循环处理的,要想访问二维数组a的所有元素,需要两个嵌套循环,如

for (double[] row : a)
for (double value : row)
do something with value

10.6 不规则组

注意由于Java实际上没有多维数组概念,前面提到的多维实际上是数组的数组,因此,可以构造不规则的数组,即数组的每一行有不同的长度。
当需要创建一个不规则数组时,首先需要分配一个具有所含行数的数组

int[][] a = new int[NMAX+1][];

接下来,再分配这些行

for (int n=0; n<=NMAX; n++)
a[n] = new int[n+1];

从而生成了一个三角矩阵。