Java 的 “特殊密码”
(一)关键字:被赋予特殊含义的字符串
在 Java 的世界里,关键字是被 Java 语言赋予了特殊含义,用作专门用途的字符串。这些关键字就像是 Java 程序的特殊密码,有着独特的作用和意义。它们的特点十分鲜明,所有字母都为小写,这是 Java 语言为了让代码风格更加统一和规范而设定的规则。例如,class关键字用于定义类,它是 Java 面向对象编程的基础,通过class我们可以创建各种具有特定属性和行为的对象;int关键字用于声明整数类型的变量,让我们能够在程序中处理整数数据;if关键字则用于条件判断,根据不同的条件执行不同的代码块,为程序的逻辑控制提供了支持。
这些关键字是 Java 语言的核心组成部分,它们不能用作变量名、方法名、类名、包名和参数。想象一下,如果我们把class当作变量名来使用,那么 Java 编译器在解析代码时就会陷入混乱,无法准确理解我们的意图。所以,严格遵守关键字的使用规则,是编写正确 Java 程序的基础。
(二)保留字:未来可能的关键字
除了关键字,Java 中还有保留字的概念。保留字是现在 Java 尚未使用,但以后版本可能会作为关键字使用的标识符。虽然它们在当前的 Java 版本中没有实际的功能,但为了保证代码的兼容性和未来的可扩展性,我们在编程时应避免使用它们。
比如goto和const,这两个就是 Java 中的保留字。在其他编程语言中,goto可能用于实现无条件跳转,const用于定义常量,但在 Java 中,它们目前没有被赋予这样的功能。然而,说不定在未来的 Java 版本中,它们会被启用并具有特定的用途。所以,为了避免潜在的问题,我们在给变量、类、方法等命名时,一定要避开这些保留字。
标识符:你的 Java 命名指南
在 Java 编程中,标识符就像是我们给各种程序元素起的名字,它是一个非常重要的概念。凡是可以自己命名的地方都叫标识符,比如包名、类名、方法名、变量名、接口名等等 ,这些名字就像我们生活中的名字一样,用来区分和标识不同的事物。在 Java 程序里,标识符的作用至关重要,它让我们能够准确地引用和操作各种程序元素。
(一)什么是标识符
标识符是我们在 Java 编程中给各种元素取的名字,它就像是我们在现实生活中给人、物取的名字一样,用于区分和标识不同的事物。在 Java 中,包名、类名、方法名、变量名、接口名等都是标识符的具体体现。例如,我们定义一个名为User的类,这里的User就是一个标识符,它代表了我们定义的这个类;再比如,我们定义一个方法printHello,printHello就是这个方法的标识符,通过这个名字我们可以调用这个方法来执行相应的功能。
(二)合法标识符规则
- 组成规则:Java 中的标识符由 26 个英文字母大小写、0-9 的数字、下划线(_)或美元符号(\()组成。这就像是一个密码组合,只能由这些特定的字符组成。例如,`userName`、`_age`、`\)count` 都是符合组成规则的标识符。
- 开头规则:标识符不能以数字开头。想象一下,如果我们定义一个变量名为1number,这就违反了开头规则,Java 编译器会无法识别这个标识符,从而报错。正确的做法应该是将数字放在字母、下划线或美元符号之后,比如number1。
- 关键字和保留字规则:标识符不可以使用关键字和保留字,但能包含关键字和保留字。关键字是 Java 语言赋予特殊含义的字符串,保留字是未来可能成为关键字的字符串,它们都有特定的用途,所以不能直接用作标识符。例如,我们不能将变量命名为class,因为class是 Java 的关键字;但我们可以命名为myClass,这里包含了class,但不是直接使用。
- 大小写规则:Java 中严格区分大小写,这意味着myVar和myVAR是两个不同的标识符。就像我们在生活中,同样的字母组合,大小写不同代表的含义可能也不同。所以在编写 Java 代码时,一定要注意标识符的大小写。
- 空格规则:标识符不能包含空格。比如,我们不能定义一个变量名为user name,中间有空格是不允许的,正确的应该是userName这样没有空格的形式。
(三)命名规范
- 包名:多单词组成时所有字母都小写,例如com.example.demo。包名就像是一个文件夹的名字,全部小写可以让代码结构看起来更加清晰和整齐。通常,包名会采用公司域名反转的形式,后面再跟上项目名和模块名等,这样可以保证包名的唯一性,也方便管理和查找代码。
- 类名、接口名:多单词组成时,所有单词的首字母大写,这就是我们常说的大驼峰命名法。比如UserService、LoginInterface。类名和接口名通常是名词或名词短语,这种命名方式能够清晰地表达它们所代表的含义,让其他开发者一眼就能看出这个类或接口的大致功能。
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写,这就是小驼峰命名法。例如userName、getUserInfo。变量名和方法名一般为动词或动词短语,与参数或参数名共同组成动宾短语,这样可以准确地描述变量的用途和方法的功能。
- 常量名:所有字母都大写,多单词时每个单词用下划线连接,例如MAX_COUNT、USER_NAME_LENGTH。常量在程序运行过程中值是不变的,全大写并用下划线连接的命名方式可以突出常量的特点,让代码阅读者一眼就能识别出这是一个常量。
变量:数据的小容器
在 Java 编程中,变量是一个非常基础且重要的概念,它就像是一个个小容器,用于存储各种数据,是程序中最基本的存储单元。无论是简单的数学计算,还是复杂的业务逻辑处理,都离不开变量的使用。掌握变量的相关知识,是深入学习 Java 编程的基石。
(一)变量的概念与作用
变量可以理解为内存中的一个存储区域,这个区域就像是一个小房间,专门用来存放数据。而且这个区域中的数据可以在同一类型范围内不断变化,就像房间里的物品可以随时更换一样。变量由变量类型、变量名和存储的值这三部分组成。变量类型决定了这个 “小房间” 能存放什么样的数据,比如是整数、小数还是文本等;变量名则是给这个 “小房间” 取的名字,方便我们在程序中找到它;存储的值就是存放在这个 “小房间” 里的数据。
变量在程序中的作用至关重要,它主要用于在内存中保存数据。我们可以把变量看作是一个临时的数据存储点,在程序运行过程中,数据可能会不断地被读取、修改和使用,而变量就为这些数据提供了一个稳定的存储和操作空间。例如,在一个计算商品总价的程序中,我们可以定义一个变量来存储商品的单价,另一个变量存储商品的数量,然后通过这两个变量计算出总价。在这个过程中,变量就像是一个个数据的 “搬运工”,将不同的数据进行存储和传递,最终帮助我们完成程序的功能。
(二)变量的声明、赋值与使用
在 Java 中,使用变量需要遵循一定的规则,首先要对变量进行声明。声明变量的语法很简单,就是 “数据类型 变量名称” ,比如int age; ,这里int是数据类型,表示这是一个整数类型的变量,age是变量名,我们通过这个名字来引用这个变量。声明变量的过程就像是在内存中申请了一个 “小房间”,并给这个 “小房间” 取了个名字。
声明变量后,通常需要给变量赋值,赋值的语法是 “变量名称 = 值” ,例如age = 20; ,这就表示将值20存放到了名为age的变量中。也可以在声明变量的同时进行赋值,例如int age = 20; ,这样一步到位,既声明了变量又给它赋了初始值。
需要注意的是,Java 中每个变量必须要先声明,后使用。如果我们试图使用一个未声明的变量,编译器会报错,就像你要去一个不存在的房间取东西,肯定是找不到的。例如下面这段代码:
public class VariableTest {
public static void main(String[] args) {
System.out.println(score); // 这里会报错,因为score变量未声明
int score = 90;
}
}
在上面的代码中,System.out.println(score);这行代码在score变量声明之前就试图使用它,所以会导致编译错误。正确的做法是先声明变量,再使用它,修改后的代码如下:
public class VariableTest {
public static void main(String[] args) {
int score = 90;
System.out.println(score);
}
}
这样,程序就能正常运行并输出score的值。
(三)成员变量与局部变量
在 Java 中,根据变量声明位置的不同,可分为成员变量和局部变量。在方法体外,类体内声明的变量称为成员变量;在方法体内部声明的变量称为局部变量。这两种变量在很多方面都存在差异。
从生命周期来看,它们都有自己的生命周期。成员变量随着对象的创建而存在,随着对象的销毁而消失;局部变量则在方法被调用时创建,在方法执行结束后消失。例如,我们定义一个Person类,其中有一个成员变量name,还有一个方法sayHello,方法中有一个局部变量message:
public class Person {
// 成员变量
String name;
public void sayHello() {
// 局部变量
String message = "Hello, ";
System.out.println(message + name);
}
}
当我们创建一个Person对象时,成员变量name就会被分配内存空间,直到这个对象被垃圾回收机制回收,name才会消失;而在调用sayHello方法时,局部变量message被创建,方法执行完毕后,message就会从内存中被释放。
在初始化方面,二者存在一些不同。成员变量如果没有显式地初始化,系统会为其赋予默认值,比如整数类型的默认值是0,布尔类型的默认值是false ,字符串类型的默认值是null等。而局部变量除形参外,需要在使用前进行初始化,否则会编译错误。例如:
public class VariableDifference {
// 成员变量,未初始化,有默认值
int memberVariable;
public void testMethod() {
// 局部变量,未初始化,直接使用会报错
int localVariable;
System.out.println(localVariable); // 这里会编译错误
}
}
在上面的代码中,memberVariable作为成员变量,即使没有初始化,也有默认值0;而localVariable作为局部变量,在未初始化的情况下使用,就会导致编译错误。正确的做法是在使用localVariable之前对其进行初始化,比如int localVariable = 10; 。
基本数据类型:Java 的基石
在 Java 编程中,基本数据类型是构建程序的基础,它们就像是搭建高楼大厦的基石,每一种基本数据类型都有其独特的用途和特点。了解和掌握这些基本数据类型,对于编写高效、准确的 Java 程序至关重要。
(一)整数类型
Java 中的整数类型包括byte、short、int和long,它们分别用于存储不同范围的整数值。
- byte:占用 1 个字节(8 位),取值范围是 -128 到 127。它通常用于存储较小的整数,比如在处理图像像素数据时,每个像素的颜色分量可能只需要 0 到 255 的值,这时byte就足够了,而且可以节省大量的内存。例如:
byte num1 = 127; // 声明一个byte类型的变量num1,并赋值为127
- short:占用 2 个字节(16 位),取值范围是 -32,768 到 32,767。当需要存储比byte更大但又不需要int全部范围的整数时,short是一个不错的选择。比如在网络传输或存储大量短整数时,使用short可以减少内存消耗。示例代码如下:
short num2 = 32767; // 声明一个short类型的变量num2,并赋值为32767
- int:占用 4 个字节(32 位),取值范围是 -2^31 到 2^31 - 1,即 -2,147,483,648 到 2,147,483,647。这是最常见的整数类型,大多数整数运算默认使用int。除非特别指定,局部变量和方法参数通常都是int类型。例如:
int num3 = 2147483647; // 声明一个int类型的变量num3,并赋值为int的最大值
- long:占用 8 个字节(64 位),取值范围是 -2^63 到 2^63 - 1,即大约 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。当需要存储或处理非常大的整数时,比如银行账户交易额、时间戳、计数器等,使用long可以避免整数溢出的风险。需要注意的是,Java 的整型常量默认为int型,声明long型常量须后加 ‘l’或’L’。示例如下:
long num4 = 9223372036854775807L; // 声明一个long类型的变量num4,并赋值为long的最大值,注意后面的L
(二)浮点类型
浮点类型用于表示小数,Java 中有两种浮点类型:float和double。
- float:表示单精度浮点数,占用 4 个字节的内存空间。Java 的浮点型常量默认为double型,声明float型常量,须后加‘f’或‘F’。它的精度为 6 到 7 位有效数字,指数范围是 -127 到 128 ,取值范围大约是 -3.40E+38 到 +3.40E+38 。例如:
float num5 = 3.14F; // 声明一个float类型的变量num5,并赋值为3.14,注意后面的F
- double:表示双精度浮点数,占用 8 个字节的内存空间。它的精度为 15 到 16 位有效数字,指数范围是 -1023 到 1024 ,取值范围大约是 -1.79E+308 到 +1.79E+308 。double类型的取值范围比float类型更大且精度更高,在需要表示较大或需要更高精度的浮点数时,通常使用double。例如:
double num6 = 3.141592653589793; // 声明一个double类型的变量num6,并赋值为一个高精度的小数
(三)字符类型
char类型用于表示字符,占用 2 个字节(16 位)。在 Java 中,所有字符都使用 Unicode 编码,这意味着一个char类型的变量可以存储一个字母、一个汉字或者其他书面语的一个字符。字符常量是用单引号括起的一个字符,例如char c1 = 'a'; 。
char类型是可以进行运算的,因为它都对应有 Unicode 码。在 Java 中,对char类型字符运算时,直接当做 ASCII 表(ASCII 是 Unicode 的一个子集)对应的整数来对待。例如:
char ch = 'a';
System.out.println(ch + 1); // 输出98,因为'a'在ASCII表中对应的数值是97,97 + 1 = 98
还可以通过使用字符与整数做算术运算,得出字符对应的数值。例如:
char ch1 = 'A';
System.out.println((int)ch1); // 输出65,获取'A'在ASCII表中对应的数值
(四)布尔类型
boolean类型用于表示布尔值,即逻辑真或假,它只有两个取值:true和false,并且boolean类型不可以转换为其它的数据类型 ,也不能与其他基本数据类型运算。在 Java 中,boolean类型通常用于流程控制,比如在if语句、while语句、do - while语句、for语句中,通过判断boolean类型的值来决定程序的执行流程。例如:
boolean flag = true;
if (flag) {
System.out.println("条件为真,执行此代码块");
} else {
System.out.println("条件为假,执行此代码块");
}
(五)类型转换
在 Java 编程中,经常会遇到需要将一种数据类型转换为另一种数据类型的情况,这就涉及到类型转换。类型转换分为自动类型转换(隐式)和强制类型转换(显式)。
自动类型转换:
- 特点:代码不需要进行特殊处理,自动完成。
- 规则:数据范围从小到大,也就是把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。例如,int类型可以自动转化为long类型:
int num7 = 10;
long num8 = num7; // 自动类型转换,int类型的num7自动转换为long类型赋值给num8
需要注意以下几点:
- byte、short、char之间不会相互转换,他们三者在计算时首先转换为int类型。例如:
byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2; // 这行代码会报错,因为b1和b2在计算时会自动转换为int类型,int类型不能直接赋值给byte类型
int result1 = b1 + b2; // 正确,使用int类型接收计算结果
- boolean类型不能与其它数据类型运算。
- 当把任何基本数据类型的值和字符串(String)进行连接运算时 (+),基本数据类型的值将自动转化为字符串(String)类型。例如:
int num9 = 10;
String str = "数字是:" + num9;
System.out.println(str); // 输出:数字是:10
强制类型转换:
- 特点:代码需要进行特殊的格式处理,不能自动完成。
- 规则:数据范围由大到小,也就是把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量。格式为:目标数据类型 变量名 = (目标数据类型) 值或者变量。例如,将long类型转换为int类型:
long num10 = 100L;
int num11 = (int)num10; // 强制类型转换,将long类型的num10强制转换为int类型赋值给num11
需要注意的是,强制类型转换可能会造成精度降低或数据溢出。例如,将一个较大的double类型值强制转换为int类型时,小数部分会被直接舍弃:
double num12 = 5.5;
int num13 = (int)num12;
System.out.println(num13); // 输出5,小数部分.5被舍弃
运算符:数据的魔法棒
在 Java 编程中,运算符就像是神奇的魔法棒,能够对数据进行各种操作和运算,让我们的程序能够实现丰富多彩的功能。运算符的种类繁多,每种都有其独特的用途和规则。接下来,我们就一起来深入了解 Java 中的各种运算符。
(一)算术运算符
算术运算符是我们在数学运算中最常用的运算符,在 Java 中也不例外。它包括加(+)、减(-)、乘(*)、除(/)、取余(%)、自增(++)、自减(--)运算符。
- 加(+)、减(-)、乘(*)、除(/)、取余(%)运算符:这些运算符的功能和我们在数学中所学的基本一致。例如,int result1 = 5 + 3; ,这里的+运算符将5和3相加,结果8赋给result1;int result2 = 10 - 4; ,-运算符实现减法,结果6赋给result2;int result3 = 6 * 7; ,*运算符执行乘法,结果42赋给result3;int result4 = 15 / 3; ,/运算符进行除法,结果5赋给result4。需要注意的是,在整数除法中,如果不能整除,结果会截断为整数,小数部分被丢弃。例如int result5 = 10 / 3; ,结果是3,而不是3.333... 。取余运算符%用于获取除法运算的余数,比如int result6 = 17 % 5; ,结果是2,因为17除以5,商是3,余数是2。
- 自增(++)、自减(--)运算符:自增和自减运算符是比较特殊的算术运算符,它们可以使变量的值自动增加或减少 1。自增运算符有两种形式:前置自增(++a)和后置自增(a++);自减运算符也有前置自减(--a)和后置自减(a--)两种形式。前置自增和后置自增的区别在于,前置自增是先将变量的值加 1,然后再使用变量的值;后置自增是先使用变量的值,然后再将变量的值加 1。例如:
int a = 5;
int b = ++a; // 先将a加1,a变为6,然后将6赋给b,此时a=6,b=6
int c = 5;
int d = c++; // 先将c的值5赋给d,然后c再加1,此时c=6,d=5
自减运算符的原理和自增运算符类似,前置自减是先减 1 再使用,后置自减是先使用再减 1。例如:
int e = 8;
int f = --e; // 先将e减1,e变为7,然后将7赋给f,此时e=7,f=7
int g = 8;
int h = g--; // 先将g的值8赋给h,然后g再减1,此时g=7,h=8
(二)赋值运算符
赋值运算符用于将右边的值赋给左边的变量,基本的赋值运算符是 “=”。例如int num = 10; ,就是将10这个值赋给num变量。除了基本的赋值运算符,还有一些复合赋值运算符,如+=、-=、*=、/=、%=等 。这些复合赋值运算符是将赋值和算术运算结合起来,使代码更加简洁。例如int a = 5; a += 3; ,这等价于a = a + 3; ,执行后a的值变为8。同样,a -= 2; 等价于a = a - 2; ,a *= 4; 等价于a = a * 4; ,a /= 2; 等价于a = a / 2; ,a %= 3; 等价于a = a % 3; 。
还可以进行连续赋值,例如int a, b, c; a = b = c = 10; ,这表示先将10赋给c,然后将c的值赋给b,最后将b的值赋给a,最终a、b、c的值都为10。在连续赋值中,赋值运算符是从右向左结合的,这是一个需要注意的点。
(三)比较运算符
比较运算符用于比较两个值的大小或是否相等,其结果是一个boolean类型的值,即true或false。比较运算符包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)。例如:
int num1 = 10;
int num2 = 5;
System.out.println(num1 > num2); // 输出true,因为10大于5
System.out.println(num1 < num2); // 输出false,因为10不小于5
System.out.println(num1 >= num2); // 输出true,因为10大于等于5
System.out.println(num1 <= num2); // 输出false,因为10不小于等于5
System.out.println(num1 == num2); // 输出false,因为10不等于5
System.out.println(num1!= num2); // 输出true,因为10不等于5
需要注意的是,==在比较基本数据类型时,比较的是值是否相等;而在比较引用数据类型时,比较的是对象的内存地址是否相等。例如:
int a = 5;
int b = 5;
System.out.println(a == b); // 输出true,因为a和b的值相等
String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");
System.out.println(str1 == str2); // 输出true,因为str1和str2指向常量池中的同一个字符串对象
System.out.println(str1 == str3); // 输出false,因为str1和str3是不同的对象,内存地址不同
(四)逻辑运算符
逻辑运算符用于连接布尔型表达式,对布尔值进行逻辑运算,其结果也是boolean类型。逻辑运算符包括与(&)、或(|)、非(!)、短路与(&&)、短路或(||)。
- 与(&)和短路与(&&):&和&&都表示 “且” 的关系,当符号左右两边布尔值都是true时,结果才能为true,否则为false。它们的区别在于,&无论左边的条件是true还是false,右边的条件都会进行判断;而&&如果左边的条件是false,则不会再判断右边的条件,直接返回false,这就是所谓的短路效果。例如:
int a = 5;
int b = 3;
System.out.println((a > 3) & (b++ > 2)); // 输出true,b++会执行,b变为4
System.out.println((a > 3) && (b++ > 2)); // 输出true,因为a > 3为true,所以会继续判断b++ > 2,b++会执行,b变为5
System.out.println((a > 10) & (b++ > 2)); // 输出false,b++会执行,b变为6
System.out.println((a > 10) && (b++ > 2)); // 输出false,因为a > 10为false,所以不会判断b++ > 2,b还是6
- 或(|)和短路或(||):|和||都表示 “或” 的关系,当符号两边布尔值有一边为true时,结果为true,当两边都为false时,结果为false。|无论左边的条件是true还是false,右边的条件都会进行判断;而||如果左边的条件是true,则不会再判断右边的条件,直接返回true。例如:
int c = 5;
int d = 3;
System.out.println((c > 3) | (d++ > 2)); // 输出true,d++会执行,d变为4
System.out.println((c > 3) || (d++ > 2)); // 输出true,因为c > 3为true,所以不会判断d++ > 2,d还是3
System.out.println((c > 10) | (d++ > 2)); // 输出true,d++会执行,d变为4
System.out.println((c > 10) || (d++ > 2)); // 输出true,因为d++ > 2为true,所以会判断d++ > 2,d++会执行,d变为4
- 非(!):!表示 “非” 的关系,当变量布尔值为true时,结果为false;当变量布尔值为false时,结果为true。例如boolean flag = true; System.out.println(!flag); ,输出false。
(五)位运算符
位运算是直接对整数的二进制进行的运算,它包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)、无符号右移(>>>)。位运算符在一些底层编程和算法中经常会用到,比如在图像处理、加密算法等领域。
以左移(<<)和右移(>>)运算符为例,左移运算符<<是将左边的操作数按位左移右边操作数指定的位数,右边空出的位用 0 填充。例如int num = 5; // 5的二进制是00000101 int result = num << 2; // 左移2位后,二进制变为00010100,结果是20 。右移运算符>>是将左边的操作数按位右移右边操作数指定的位数,左边空出的位用符号位填充(正数用 0 填充,负数用 1 填充)。例如int num2 = -5; // -5的二进制是11111011 int result2 = num2 >> 2; // 右移2位后,二进制变为11111110,结果是-2 。
(六)三元运算符
三元运算符也叫条件运算符,它是 Java 中唯一的一个三目运算符,语法形式为:布尔表达式?表达式 1:表达式 2。其运算规则是,如果布尔表达式的值为true,则返回表达式 1 的值;如果布尔表达式的值为false,则返回表达式 2 的值。例如:
int a = 10;
int b = 5;
int max = (a > b)? a : b; // 因为a > b为true,所以max的值为a,即10
再比如,我们可以用三元运算符来判断一个数是奇数还是偶数:
int num = 7;
String result = (num % 2 == 0)? "偶数" : "奇数"; // 因为7 % 2!= 0,所以result的值为"奇数"
(七)运算符优先级
在一个复杂的表达式中,可能会包含多个不同的运算符,这时运算符的优先级就决定了运算的先后顺序。如果不了解运算符优先级,可能会导致程序出现意想不到的结果。例如int result = 2 + 3 * 4; ,按照运算符优先级,乘法先于加法执行,所以结果是2 + 12 = 14,而不是5 * 4 = 20。
常见运算符的优先级顺序如下(从高到低):
- 括号(()):括号内的表达式优先计算,括号可以改变运算的优先级,使用括号可以使表达式更加清晰易读。
- 单目运算符:如++、--(后缀递增 / 递减)、+、-(一元正负)、!(逻辑非)、~(按位取反)。
- 算术运算符:*(乘法)、/(除法)、%(取模)的优先级高于+(加法)、-(减法)。
- 位移运算符:<<(左移)、>>(右移)、>>>(无符号右移)。
- 比较运算符:<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、instanceof(判断对象是否为某个类或接口类型)的优先级高于==(等于)、!=(不等于)。
- 位运算符:按位与(&)、按位异或(^)、按位或(|)。
- 逻辑运算符:&&(短路与)的优先级高于||(短路或)。
- 三元运算符(?:)。
- 赋值运算符:=、+=、-=、*=、/=、%=等。
在编写代码时,如果对运算符的优先级不确定,最好使用括号来明确运算顺序,这样可以避免因优先级问题导致的错误,同时也能提高代码的可读性。
程序流程控制:Java 的行动指南
在 Java 编程中,程序流程控制是非常重要的一部分,它决定了程序中各个语句的执行顺序,就像我们日常生活中的行动指南一样,告诉我们先做什么,后做什么,在什么条件下做什么。Java 中主要有三种程序流程控制结构,分别是顺序结构、分支结构和循环结构。
(一)顺序结构:按部就班
顺序结构是程序中最基本的流程控制结构,它就像我们平时做事一样,按照顺序依次执行。在 Java 程序中,顺序结构就是代码由上向下逐行执行,每一行代码都按照编写的顺序依次被执行,不会出现跳跃或分支。
例如,下面这段简单的 Java 代码:
public class SequentialStructureExample {
public static void main(String[] args) {
// 声明和初始化变量
int num1 = 10;
int num2 = 20;
// 计算两个数的和
int sum = num1 + num2;
// 输出结果
System.out.println("两个数的和为:" + sum);
}
}
在这段代码中,首先声明并初始化了两个变量num1和num2,然后计算它们的和并将结果存储在sum变量中,最后输出sum的值。整个过程就是按照代码的书写顺序依次执行的,这就是顺序结构的体现。顺序结构是程序执行的基础,大多数程序都包含顺序结构的代码部分。
(二)分支结构:做出选择
分支结构也叫选择结构,它允许程序根据不同的条件做出不同的选择,执行不同的代码块。就像我们在生活中面临选择时,会根据不同的情况做出不同的决定。在 Java 中,分支结构主要有两种实现方式:if - else语句和switch - case语句。
1. if - else 语句
if - else语句是最常用的分支结构,它根据条件的真假来决定执行哪一段代码。if - else语句有三种格式:
- 单分支:if (条件) { 语句体 },当条件为真时,执行语句体中的代码,否则跳过。例如:
int score = 85;
if (score >= 60) {
System.out.println("恭喜你,考试及格了!");
}
在这个例子中,如果score大于等于 60,就会输出 “恭喜你,考试及格了!”,否则什么也不输出。
- 双分支:if (条件) { 语句体1 } else { 语句体2 },当条件为真时,执行语句体 1,否则执行语句体 2。例如:
int num = 10;
if (num % 2 == 0) {
System.out.println(num + "是偶数");
} else {
System.out.println(num + "是奇数");
}
这里根据num是否能被 2 整除来判断它是偶数还是奇数,并输出相应的结果。
- 多分支:if (条件1) { 语句体1 } else if (条件2) { 语句体2 } else if (条件3) { 语句体3 }... else { 语句体n+1 },依次判断条件,当某个条件为真时,执行对应的语句体,否则继续判断下一个条件,如果所有条件都为假,则执行else后面的语句体。例如:
int score1 = 78;
if (score1 >= 90) {
System.out.println("成绩等级为A");
} else if (score1 >= 80) {
System.out.println("成绩等级为B");
} else if (score1 >= 70) {
System.out.println("成绩等级为C");
} else if (score1 >= 60) {
System.out.println("成绩等级为D");
} else {
System.out.println("成绩等级为E");
}
根据score1的值,判断其成绩等级并输出相应的结果。
2. switch - case 语句
switch - case语句也是一种分支结构,它根据一个表达式的值来选择执行不同的代码块。语法结构为:
switch (表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n;
break;
}
其中,switch后面的括号内是一个表达式,它的值必须是byte、short、char、int、枚举(jdk 5.0)、String(jdk 7.0)类型之一。case后面跟着一个常量值,当switch表达式的值与某个case后面的值相等时,就会执行该case后面的语句体,直到遇到break语句才会跳出switch语句块。如果没有任何一个case的值与switch表达式的值相等,则会执行default后面的语句体。
例如:
int day = 3;
switch (day) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("输入错误");
break;
}
在这个例子中,根据day的值来输出对应的星期几,如果day的值不在 1 到 7 之间,则输出 “输入错误”。需要注意的是,break语句在switch - case语句中非常重要,如果没有break语句,当某个case条件满足并执行完该case的语句体后,会继续执行下一个case的语句体,直到遇到break或者switch语句结束,这就是所谓的 “case 穿透” 现象。
(三)循环结构:重复的力量
循环结构允许程序重复执行一段代码,直到满足特定的条件为止。就像我们在生活中重复做某件事情,直到达到某个目标。在 Java 中,循环结构主要有三种类型:for循环、while循环和do - while循环。
1. for 循环
for循环是一种比较常用的循环结构,它适用于已知循环次数的情况。语法结构为:
for (初始化表达式; 循环条件; 迭代因子) {
循环体;
}
其中,初始化表达式在循环开始前执行一次,通常用于初始化一个计数器变量;循环条件是一个布尔表达式,在每次循环迭代之前检查,如果条件为真,则执行循环体,否则跳出循环;迭代因子在每次循环迭代之后执行,通常用于更新计数器变量。
例如,计算 1 到 100 的和:
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("1到100的和为:" + sum);
在这个例子中,int i = 1是初始化表达式,i <= 100是循环条件,i++是迭代因子,sum += i是循环体。通过for循环,依次将 1 到 100 的整数累加到sum变量中,最终得到 1 到 100 的和。
2. while 循环
while循环的语法结构为:
while (循环条件) {
循环体;
}
先判断循环条件,如果条件为真,则执行循环体,执行完循环体后再次判断循环条件,如此反复,直到循环条件为假时,跳出循环。
例如,计算 1 到 100 的和:
int sum1 = 0;
int i = 1;
while (i <= 100) {
sum1 += i;
i++;
}
System.out.println("1到100的和为:" + sum1);
在这个例子中,首先初始化sum1为 0,i为 1,然后在while循环中,只要i小于等于 100,就将i累加到sum1中,并将i加 1,直到i大于 100 时,循环结束。
3. do - while 循环
do - while循环的语法结构为:
do {
循环体;
} while (循环条件);
先执行一次循环体,然后判断循环条件,如果条件为真,则继续执行循环体,否则跳出循环。与while循环不同的是,do - while循环至少会执行一次循环体。
例如,计算 1 到 100 的和:
int sum2 = 0;
int j = 1;
do {
sum2 += j;
j++;
} while (j <= 100);
System.out.println("1到100的和为:" + sum2);
在这个例子中,先执行sum2 += j和j++,然后判断j <= 100,如果条件为真,继续执行循环体,直到j大于 100 时,循环结束。
while与do - while的区别在于:while先判断再执行,条件不成立时,循环体一遍都不执行;do - while先执行再判断,条件不成立时,循环体至少执行一遍。
(四)特殊关键字:break 和 continue
在循环结构中,break和continue是两个特殊的关键字,它们可以改变循环的执行流程。
break语句用于终止某个语句块的执行,通常用于在循环中满足某个条件时提前结束循环。例如:
for (int k = 1; k <= 10; k++) {
if (k == 5) {
break;
}
System.out.println(k);
}
在这个例子中,当k等于 5 时,执行break语句,循环提前结束,所以只会输出 1 到 4。
continue只能使用在循环结构中,它用于跳过其所在循环语句块的一次执行,继续下一次循环。例如:
for (int l = 1; l <= 10; l++) {
if (l % 2 == 0) {
continue;
}
System.out.println(l);
}
在这个例子中,当l是偶数时,执行continue语句,跳过本次循环的剩余部分,直接进入下一次循环,所以只会输出 1、3、5、7、9。