Java 程序设计基础

Table of Contents

一个 Java 程序通常由 数据类型、变量、运算符和控制流程语句 4 部分组成,其中数据类型和运算符不仅定义了语言的规范,还决定了可以执行什么样的操作;变量是用来存储指定类型的数据,其值在程序运行期间是可变的;与变量对应的是常量,其值是固定的。

标识符和关键字

任何一种计算机语言都离不开标识符和关键字。

标识符

Java 中标识符是为方法、变量或其他用户定义项所定义的名称,标识符可以有一个或多个字符。

在 Java 语言中,标识符的构成规则如下:

  • 标识符由数字( 0~9 )和字母( A~Z a~z )、美元符号 $ 、下划线( _ )以及 Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格);
  • 标识符的第一个符号为字母、下划线和美元符号,后面可以是任何字母、数字、美元符号或下划线;
  • 区分大小写。

*注:标识符命名时,切记不能以数字开头,也不能使用任何 Java 关键字作为标识符,而且不能赋予标识符任何标准的方法名。

标识符分为两类,分别为关键字和用户自定义标识符:

  • 关键字是有特殊含义的标识符,如 true、false 表示逻辑的真假;
  • 用户自定义标识符是由用户标识符构成规则生成的非保留字的标识符。

*注:标识符不能与关键字重名。

标识符用来命名常量、变量、类和类的对象等,因此,一个良好的编程习惯要求命名标识符时,应赋予它一个意义或有用途的名字。

关键字

关键字(或者保留字)是对编译器有特殊意义的固定单词,不能在程序中做其他目的使用。它们用来表示一种数据类型,或者表示程序的结构等。

保留字是为 Java 预留的关键字,它们虽然现在没有作为关键字,在以后的升级版本中可能作为关键字。

Java 语言目前定义了 51 个关键字,这些关键字不能作为变量名、类名和方法名来使用,以下对这些关键字进行了分类:

数据类型 boolean、int、long、short、byte、float、double、char、class、interface
流程控制 if、else、do、while、for、switch、case、default、break、continue、return、try、catch、finally
修饰符 public、protected、private、final、void、static、strict、abstract、transient、synchronized、volatile、native
动作 package、import、throw、throws、extends、implements、this、super、instanceof、new
保留字 true、false、null、goto、const

注释

注释是对程序语言的说明,有助于开发者和用户之间的交流,方便理解程序。注释不是编程语句,因此被编译器忽略。

单行注释 ,以双斜杠 // 标识,只能注释一行内容,用在注释信息内容少的地方。

多行注释 ,包含在 /**/ 之间,能注释很多行的内容。注意:多行注释可以嵌套单行注释,但是不能嵌套多行注释和文档注释。

文档注释 ,包含在 /***/ 之间,也能注释多行内容,一般用在类、方法和变量上面,用来描述其作用。注释后,鼠标放在类和变量上面会自动显示出我们注释的内容。

文档注释可以通过 javadoc 命令把文档注释中的内容生成文档,并输出到 HTML 文件中,方便记录程序信息。还可以包含一个或多个 @ 标签,每个 @ 标签都在新的一行开始。

在 Java 中,一行注释以双斜杠 // 标识;多行注释包含在 /**/ 之间;文档注释包含在 /***/ 之间。

当编译器执行到 // 时,就会忽略该行 // 之后的所有文本;当执行到 /* 时,会扫描下一个 */ 并忽略 /**/ 之间的任何文本;当执行到 /** 时,也会扫描下一个 */ 并忽略 /***/ 之间的任何文本内容。

TODO Javadoc 文档注释

常量

常量是指在程序的整个运行过程中值保持不变的量。

*注意:常量和常量值是不同的概念,常量值是常量的具体和直观的表现形式,常量是形式化的表现。常在程序中既可以直接使用常量值,也可以使用常量。

说得很绕,其实没什么用……

常量值

常量值又称为字面常量,它是通过数据直接表示,如整型、字符串等。

1. 整型常量值

Table 1: Java 的整型常量值主要形式
十进制数形式   54、-67、0
八进制数形式 0 开头 0125、-013
十六进制数形式 0x0X 开头 0x100、-0x16

整型( int )常量默认在内存中占 32 位,是具有整数类型的值,当运算过程中所需值超过 32 位长度时,可以把它表示为长整型( long )数值,通过在数字后面加 L、l 表示,如 697L ,它在内存中占 64 位。

2. 实型常量值

Table 2: Java 的实型常量值主要形式
十进制数形式 由数字和小数点组成,且必须有小数点 12.34、-98.0
科学计数法形式 其中 e、E 之前必须有数字,且之后的数字必须为整数 1.75e5、32&E3

Java 实型常量默认在内存中占 64 位,是具有双精度型( double )的值。

如果考虑到需要节省运行时的系统资源,而运行时的数据值取值范围并不大且运算精度要求不太高的情况,可以把它表示为单精度型( float )的数值。

单精度型数值一般要在该常数后面加 F、f ,如 67.9f ,表示一个 float 型实数,它在内存中占 32 位(取决于系统的版本高低)。

3. 布尔型常量值

Java 的布尔型常量只有两个值,即 false (假)和 true (真)。

4. 字符型和字符串常量值

Java 的字符型常量值是用单引号引起来的一个字符,如 'e'、'E'

注意: *Java 字符串常量值中的单引号和双引号不可混用 ,双引号用来表示字符串,像 "11"、"d" 等都是表示单个字符的字符串。

除了以上所述形式的字符常量值之外,Java 还允许使用一种特殊形式的字符常量值来表示一些难以用一般字符表示的字符,这种特殊形式的字符是经开头的字符序列,称为 转义字符

Table 3: Java 中常用的转义字符
转义字符 说明
\ddd 1~3 位八进制数所表示的字符
\uxxxx 1~4 位十六进制数所表示的字符
\' 单引号字符
\" 双引号字符
\\ 双斜杠字符
\r 回车
\n 换行
\b 退格
\t 横向跳格

定义常量

常量不同于常量值,它可以在程序中用符号来代替常量值使用,因此在使用前必须先定义。在声明常量的同时要赋予一个初始值,常量一旦初始化就不可以被修改。

Java 语言中使用 final 关键字来定义一个常量,其语法如下所示:

final dataType variableName = value

其中, final 是定义常量的关键字, dataType 指明常量的数据类型, variableName 是变量的名称, value 是初始值。

final 关键字表示是最终的,它可以修改很多元素,修饰变量就变成了常量。常量有三种类型:静态常量、成员常量和局部常量。来看个例子吧:

 1: public class HelloWorld {
 2:     // 静态常量
 3:     public static final double PI = 3.14;
 4:     // 声明成员常量
 5:     final int y = 10;
 6: 
 7:     public static void main(String[] args) {
 8:         // 声明局部常量
 9:         final double x = 3.3;
10:     }
11: }

我们来稍微分析一下上面这段代码吧。

代码第 3 行的是声明静态常量,使用在 final 之前用 public static 修饰。 public static 修饰的常量作用域是全局的,不需要创建对象就可以访问它,在类外部访问形式为 HelloWorld.PI ;代码第 5 行声明成员常量,作用域类似于成员变量,但不能修改;代码第 9 行声明局部常量,作用域类似于局部变量,但不能修改。

在定义常量时,需要注意如下内容:

  • 在定义常量时就需要对该常量进行初始化;
  • final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法;
  • 为了与变量区别,常量取名一般都用大写字符。

当常量被设定后,一般情况下不允许再进行更改,如果更改其值将提示错误。

常量(constant)是程序中使用的一个确定数值,在汇编阶段就可以确定,直接编码于指令代码中,不是保存在存储器中可变的变量,因为是编码在指令中的量,和指令一起存储了,所以不用单独开辟主存空间,所以也就没法动态改变它了,这也正是高级语言常量无法修改的原因。

变量

Java 语言是强类型(Strongly Typed)语言,强类型包含以下两方面的含义:

  • 所有的变量必须先声明、后使用;
  • 指定类型的变量只能接受类型与之匹配的值。

这意味着 每个变量和每个表达式都有一个在编译时就确定的类型 ,类型限制了一个变量能被赋的值,限制了一个表达式可以产生的值,限制了在这些值上可以进行的操作,并确定了这些操作的含义。

常量和变量是 Java 程序中最基础的两个元素,常量的值是不能被修改的,而变量的值在程序运行期间可以被修改。

声明变量

对开发人员来说,变量是用来描述一条信息的别名,可以在程序代码中使用一个或多个变量。其基本语法如下:

// 声明变量
DataType identifier;
// 声明变量并赋值
DataType identifier = value;

其中:

  • DataType :变量类型,如 int、string、char、double 等;
  • identifier :标识符,也叫变量名称;
  • value :声明变量时的值。

来看一段实例代码吧。

1: String employee;                // String 类型的变量
2: boolean isSave;                 // boolean 类型的变量
3: int create_at;                  // int 类型的变量

变量赋值

初始化变量是为变量指定一个明确的初始值。初始化变量有两种方式:一种是声明时直接赋值,另一种是先声明、后赋值。另外,多个类型的变量可以同时定义或者初始化,但是多个变量中间要使用逗号分隔,声明结束时用分号分隔。

老规矩,看代码。
 1: // 声明并赋值
 2: char usersex = '女';
 3: 
 4: // 先声明,后赋值
 5: String username;
 6: username = "小明";
 7: 
 8: // 声明多个变量
 9: String username, address, phone, tel;
10: // 声明并初始化多个变量
11: int num1 = 12, num2 = 23, result = 35;

Java 中初始化变量时需要注意以下事项:

  • 变量是类或者结构中的字段,如果没有显示地初始化,默认状态下创建变量并默认初始值为 0 ;
  • 方法中的变量必须显式地初始化,否则在使用该变量时就会出错。

变量作用域

变量的作用域规定了变量所能使用的范围,只有在作用域内变量才能被使用。根据变量声明地点的不同,变量的作用域也不同。

根据作用域的不同,一般将变量分为不同的类型:成员变量和局部变量。

1. 成员变量

Java 的成员变量有两种,分别是 全局变量和静态变量 (类变量)。 定义在方法体和语句块之外 ,不属于任何一个方法,作用域是整个类。

名称 修饰 访问 生命周期
全局变量(实例变量) static 修饰 对象名.变量名 只要对象被当作引用,实例变量就将存在
静态变量(类变量) static 修饰 类名.变量名对象名.变量名 其生命周期取决于类的生命周期,类被垃圾回收机制彻底回收时才会被销毁

2. 局部变量

局部变量 是指在方法或者方法代码块中定义的变量,其作用域是其所在的代码块。可分为以下三种:

  • 方法参数变量(形参):在整个方法内有效;
  • 方法局部变量(方法内定义):从定义这个变量开始到方法结束这一段时间内有效;
  • 代码块局部变量(代码块内定义):从定义这个变量开始到代码块结束这一段时间内有效。

局部变量在使用前必须被程序员主动初始化值。

数据类型

Java 语言支持的数据类型分为两种:基本数据类型(Primitive Type)和引用数据类型(Reference Type)。

基本数据类型

Table 4: Java 的基本数据类型
类型名称 关键字 占用内存(字节) 取值范围
字节型 byte 1 -128~127
短整型 short 2 -32768~32767
整型 int 4 -2147483648~2147483647
长整型 long 8 -9223372036854775808L~9223372036854775807L
单精度浮点型 float 4 +/-3.4E+38F(6~7 个有效位)
双精度浮点型 double 8 +/-1.8E+308 (15 个有效位)
字符型 char 2 ISO 单一字符集
布尔型 boolean 1 true 或 false

*提示: char 代表字符型,实际上字符型也是一种整数类型,相当于无符号整数的类型。

所有的基本数据类型的大小(所占用的字节数)都已明确规定,在各种不同的平台上保持不变,这特性有助于提高 Java 程序的可移植性。

Java 是一种强类型的语言 ,所有的变量都必须先明确定义其数据类型,然后才能使用。

基本数据类型又可分为 4 大类(如上表):

  • 整数类型(byte、short、int、long);
  • 浮点类型(floa、double);
  • 布尔类型(boolean);
  • 字符类型(char)。

1. 整数类型

Table 5: Java 整数类型变量说明
名称 说明
字节型(byte) byte 类型是最小的整数类型。当用户从网络或文件中处理数据流时,或者处理可能 与 Java 的其他内置类型不直接兼容的未加工的二进制数据 时,该类型非常有用
短整型(short) short 类型限制数据的存储为先高字节,后低字节,这样在某些机器中会出错,因此该类型很少被使用
整型(int) int 类型是最常用的一种整数类型
长整型(long) 对于大型程序常会遇到很大的整数,当超出 int 类型所表示的范围时就要使用 long 类型

2. 浮点类型

浮点类型是带有小数部分的数据类型,也叫实型。

浮点类型包括单精度浮点型(float)和双精度浮点型(double),代表有小数精度的数字。它们的区别主要是所占用的内存大小不同,float 类型占用 4 字节的内存空间,double 类型占用 8 字节的内存空间。

Java 默认的浮点型为 double ,例如 11.11 和 1.233 都是 double 类型。如果要说明一个 float 类型数值,就 必须 在其后追加字母 f、F ,如 11.11f 。

3. 布尔类型

布尔类型(boolean)用于对两个数值通过逻辑运算,判断结果是“真”还是“假”。Java 中用保留字 truefalse 来代表逻辑运算中的“真”和“假”。因此,一个 boolean 类型的变量或表达式只能是取 truefalse 这两个值中的一个。

在 Java 语言中,布尔类型的值不能转换成任何数据类型, true 常量不等于 1,而 false 常量也不等于 0。这两个值只能赋给 boolean 类型的变量,或者用于布尔表达式中。

4. 字符类型

Java 语言中的字符类型(char)使用两个字节的 Unicode 编码表示,它支持世界上所有语言,可以使用单引号字符对 char 型赋值。

一般计算机语言使用 ASCII 编码,用一个字节表示一个字符。ASCII 码是 Unicode 码的一个子集,用 Unicode 表示 ASCII 码时,其高字节为 0 ,它是前 255 个字符。

Unicode 字符通常用十六进制表示,范围从 "\u0000" ~ "\uffff" ,即从 0~65535 。例如 "\u0000" ~ "\u00ff" 表示 ASCII 码集。 "\u" 表示转义字符,它用来表示其后 4 个十六进制数字是 Unicode 码。

来看一段示例代码吧。

1: public static void main(String[] args) {
2:     char a = 'A';    // 向 char 类型的 a 变量赋值为 A,所对应的 ASCII 值为 65
3:     char b = 'B';    // 向 char 类型的 b 变量赋值为 B,所对应的 ASCII 值为 66
4:     System.out.println("A 的 ASCII 值与 B 的 ASCII 值相加结果为:"+(a+b));
5: }

引用数据类型

引用数据类型建立在基本数据类型的基础上,包括数组、类和接口。引用数据类型是由用户自定义,用来限制其他数据的类型。另外,Java 语言中不支持 C++ 中的指针类型、结构类型、联合类型和枚举类型。

引用类型还有一种特殊的 null 类型。所谓引用数据类型就是对一个对象的引用,对象包括实例和数两种。

实际上,引用类型变量就是一个指针,只是 Java 语言里不再使用指针这个说法。

空类型(null type)就是 null 值的类型,这种类型没有名称,所以也就不可能声明一个 null 类型的变量或者转换到 null 类型。

空引用( null )是 null 类型变量唯一的值,它可以转换为任何引用类型。

在实际开发中,程序员可以忽略 null 类型,假定 null 只是引用类型的一个特殊直接量。

*注:空引用( null )只能被转换成引用类型,不能转换成基本类型,因此不要把一个 null 值赋给基本数据类型的变量。

数据类型转换

数据类型的转换是在所赋值的数值和被变量接收的数据类型不一致时发生的,它需要从一种数据类型转换成另一种数据类型。数据类型的转换可以分为隐式转换(自动类型转换)和显示转换(强制类型转换)两种。

1. 隐式转换(自动类型转换)

如要以下 2 个条件满足,那么将一种类型的数据赋给另外一种类型变量时,将执行自动类型转换(automatic type conversion):

  • 两种数据类型彼此兼容;
  • 目标类型的取值范围大于源数据类型(低级类型数据转换成高级类型数据)。

当以上 2 个条件都满足时,拓宽转换(widening conversion)发生。例如,byte 类型向 short 类型转换时,由于 short 类型转换时,由于 short 类型取值范围较大,会自动将 byte 转换为 short 类型。

在运算过程中,由于不同的数据类型会转换成同一种数据类型,所以整型、浮点型以及字符型都可以参与混合运算。自动转换的规则是从低级类型数据转换成高级类型数据。转换规则如下:

  • 数值型数据的转换:byte → short → int → long → float → double ;
  • 字符型转换为整型:char → int 。

*注:char 类型比较特殊,char 自动转换成 int、long、float、double ,但 byte 和 short 不能自动转换为 char ,而且 char 也不能自动转换为 byte 或 short 。

比如说,float 、int 和 double 三种数据类型都参与了一个运算,最后输出结果就是 double 类型的,这种转换一般称为“表达式中类型的自动提升”。

自动类型提升有好处,但它也会引起令人疑惑的编译错误。例如,下面这段看起来正确的程序却会引起问题:

1: byte b = 50;
2: b = b * 2;                      // Type mismatch: cannont convert from int to byte

为什么第二行会报“类型不匹配:无法从 int 转换为 byte”的错误呢?

该程序试图将一个完全合法的 byte 类型的值 50*2 再存储给一个 byte 类型的变量,但是当表达式求值的时候,操作数被自动的提升为 int 型,计算结果也被提升为 int 型。如此以来,这样表达式的结果现在就是 int 型了,不强制转换它自然就不能被赋为 byte 型。所以,在这个特别的情况下,应该使用一个显示的强制类型转换,如下:

1: byte b = 50;
2: b = (byte)(b * 2);

这样就能产生正确的值 100 了。

2. 显示转换(强制类型转换)

当两种数据类型不兼容,或目标类型的取值范围小于源类型时,自动转换将无法时行,这时就需要进行强制类型转换。其语法格式如下:

(type)variableName

其中,type 为 variableName 要转换成的数据类型,而 variableName 是指要进行类型转换的变量名称。

在强制类型转换中,如果是将浮点型的值转换为整数,直接去掉小数点后边的所有数字;而如果是整数类型强制转换为浮点类型时,将在小数点后面补零。

Date: 2020-09-15 Tue 07:30

Author: Jack Liu

Created: 2020-10-03 Sat 11:46

Validate