Java程序设计基础
Java标识符和关键字
标识符:java相较c在标识符开头上有较小的区别,其多了美元符号$
和人民币符号¥
。其余上无太大区别——能以数字、大小写字母、下划线、美元符号、人民币符号开头,不能以数字开头。
关键字: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、supper、instanceof、new。
- 保留字:true、false、null、goto、const。
可以看到虽然Java中把goto
作为保留字,但它不支持goto
语句。
Java注释
1.单行注释:在//
之后
2.多行注释:包含在/*
和*/
之间(可以嵌套单行注释,不可嵌套多行注释和文档注释)
3.文档注释:包含在/**
和*/
之间
图2-0 文档注释示例
注:文档注释可以通过 Javadoc 命令把文档注释中的内容生成文档,并输出到 HTML 文件中,方便记录程序信息。还可以包含一个或多个 @ 标签,每个 @ 标签都在新的一行开始。
关于Javadoc(文档注释)的简单说明
文档注释只放在类、接口、成员变量、方法之前,因为Javadoc只处理这些方法的文档注释,而忽略其它地方的文档注释。
API 帮助文档相当于产品说明书,而说明书只需要介绍那些供用户使用的部分,所以 Javadoc 默认只提取 public、protected 修饰的部分。如果要提取 private 修饰的部分,需要使用 -private。
javadoc标签一般以@
开头,后跟一个制定的名字,也有以{@
开头,以}
结束。它可以识别的标签有17个,为简便我只展示四个,如下表。
标签 | 描述 | 示例 |
---|---|---|
@author | 标识一个类的作者,一般用于类注释 | @author description |
@deprecated | 指名一个过期的类或成员,表明该类或方法不建议使用 | @deprecated description |
{@docRoot} | 指明当前文档根目录的路径 | Directory Path |
@exception | 可能抛出异常的说明,一般用于方法注释 | @exception exception-name explanation |
表2-0 javadoc标签
对两种标签格式的说明:
- @tag 格式的标签(不被
{ }
包围的标签)为块标签,只能在主要描述(类注释中对该类的详细说明为主要描述)后面的标签部分(如果块标签放在主要描述的前面,则生成 API 帮助文档时会检测不到主要描述)。 - {@tag} 格式的标签(由
{ }
包围的标签)为内联标签,可以放在主要描述中的任何位置或块标签的注释中。
Javadoc 标签注意事项:
- Javadoc 标签必须从一行的开头开始,否则将被视为普通文本。
- 一般具有相同名称的标签放在一起。
- Javadoc 标签区分大小写,代码中对于大小写错误的标签不会发生编译错误,但是在生成 API 帮助文档时会检测不到该注释内容。
文档注释的格式和实现效果:
1 | package test; |
帮助文档格式如图 2-1所示。
图2-1 文档注释实现效果
值得注意的是——注释前面的*
号允许连续使用多个,其效果和使用一个*
号一样,但多个*
前不能有其他字符分隔,否则分隔符及后面的*
号都将作为文档的内容。如上述的严长生一样。
Java的常量与变量
常量
常量值又称字面量,它是通过数据直接表示的。有整型常量值(十进制、八进制0
、十六进制0x
)、实型常量值(浮点数.
、科学计数法e
或E
)、布尔型常量值(false
、true
)、字符型和字符串型常量值(双'
包裹、双"
包裹)
转义字符 | 说明 |
---|---|
\ddd | 1~3 位八进制数所表示的字符 |
\uxxxx | 1~4 位十六进制数所表示的字符 |
\‘ | 单引号字符 |
\“ | 双引号字符 |
\\ | 双斜杠字符 |
\r | 回车 |
\n | 换行 |
\b | 退格 |
\t | 横向跳格 |
表2-1 Java中常用的转义字符
常量声明格式:
1 | final dataType variableName = value |
其中final
是定义常量的关键字,dataType
指明常量的数据类型,variableName
是变量的名称,value
是初始值。
常量有三种:静态常量、成员常量和局部常量。
下面给出三种常量的声明示例:
1 | public class HelloWorld{ |
代码第3行的成员常量用public static
修饰。所以它的作用域是全局的,不需要创建对象就可以访问它,在类外访问的形式为HelloWorld.PI
。
常量定义的注意事项:
- 在定义常量时就需要对该常量进行初始化。
- final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
- 为了与变量区别,常量取名一般都用大写字符。
- 常量定义后不可修改
变量
Java语言是强类型(Strongly Typed)语言,强类型包含一下两方面含义:
- 所有的变量必须先声明后使用
- 指定类型的变量只能接受类型与之相匹配的值
Java除了在标识符的命名规范上,于首字符较C/C++增加了$
和¥
外,其余并无什么区别。
变量赋值的三种方式:
1 | char usersex='女'; // 直接赋值 |
Java中初始化变量时需要注意的事项:
- 变量是类或者结构中的字段,如果没有显示地初始化,默认状态下创建变量并默认初始值为0。
- 方法中的变量必须显示地初始化,否则在使用该变量时就会出错。
Java变量的作用域
根据作用域不同,一般将变量分为不同的类型:参选变量和局部变量。
成员变量
Java有两种成员变量:全局变量、静态变量(类变量)。
成员变量定义在方法体和语句块之外,不属于任何一个方法,作用域为整个类。表2-3对两者进行了详细说明。
名称 | 修饰 | 访问 | 生命周期 |
---|---|---|---|
全局变量(实例变量) | 无 static 修饰 | 对象名.变量名 | 只要对象被当作引用,实例变量就将存在 |
静态变量(类变量) | 用 static 修饰 | 类名.变量名或对象名.变量名 | 其生命周期取决于类的生命周期。类被垃圾回收机制彻底回收时才会被销毁 |
表2-2 成员变量
示例:
变量声明代码:
1 | public class DataClass { |
测试类代码:
1 | public class Test { |
运行结果如图2-2所示
图2-2 成员变量调用
仔细观察可以发现,name
和age
被自动赋予了默认初始值null
和0。
局部变量
局部变量可以分为三种:
- 方法参数变量(形参):在整个方法内有效。
- 方法局部变量(方法内定义): 从定义这个变量开始到方法结束这一段时间内有效。
- 代码块局部变量(代码块内定义):从定义这个变量开始到代码块结束这一段时间内有效。
下面给出三个简单示例:
1)方法局部变量
声明两个局部变量并输出其值,代码如下:
1 | public class Test2 { |
执行结果:
图2-3 执行结果
2)方法参数变量
作为方法参数声明的变量的作用域是整个方法。
声明一个方法参数变量,实现代码如下:
1 | public class Test3{ |
上述定义了一个testFun()代码,该方法中包含了一个int类型的变量n,其作用域为testFun()方法体内。输出为3。
3)代码块局部变量
代码块局部变量常用于 try catch 代码块中,成为异常处理参数变量。
异常处理参数变量的作用域是在异常处理块中,该变量是将异常处理参数传递给异常处理块,与方法参数变量类似。
声明一个异常处理语句,实现代码如下:
1 | public static Test4{ |
在上述实例中定义了异常处理语句,异常处理块 catch 的参数为 Exception 类型的变量 e,作用域是整个 catch 块。
Java数据类型
Java语言支持的数据类型分为基本数据类型(Primitive Type)和引用数据类型(Reference Type)两种。
基本数据类型
基本数据类型有八种,参见表2-0
类型名称 | 关键字 | 占用内存 | 取值范围 |
---|---|---|---|
字节型 | 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 |
表2-3 Java的基本数据类型
注:char
代表字符型,实际上字符型也是一种整数类型,相当于无符号整数类型。
Java的数据类型结构图如下
图2-4 Java数据类型结构图
Java是一种强类型语言,所有变量都有明确的数据类型,不存在“无类型”变量的概念。
基本数据类型可分为四大类:整数类型(byte、short、int、long),浮点类型(float、double)、布尔类型、字符类型。下面仅根据Java与C/C++不同的地方展开讨论。
整数类型
名称 | 说明 |
---|---|
字节型(byte) | byte 类型是最小的整数类型。当用户从网络或文件中处理数据流时,或者处理可能与 Java 的其他内置类型不直接兼容的未加工的二进制数据时,该类型非常有用。 |
短整型(short) | short 类型限制数据的存储为先高字节,后低字节,这样在某些机器中会出错,因此该类型很少被使用。 |
整型(int) | int 类型是最常使用的一种整数类型。 |
长整型(long) | 对于大型程序常会遇到很大的整数,当超出 int 类型所表示的范围时就要使用 long 类型。 |
表2-1 Java整数类型变量说明
由表2-1可知,Java较C/C++多了字节型(byte)这一整数类型,下面给出案例分析。
1 | public static void main(String[] args) { |
运行结果如下
图2-5 运行结果
注:因为 byte 类型、short 类型、int 类型和 long 类型都是整数类型,故可以使用“+”相加,而非字符串之间的连接。
浮点类型
浮点类型最大的特点就是带有小数,也被称作实型。包含了单精度浮点型(float-4字节)和双精度浮点型(double-8字节)两种。
因为Java是强类型语言,在定义浮点数时会与C/C++有略微的出入,下面给出例子:
Java的默认的浮点类型为double,如:1.111和1.7都是double型数值。如果要说明一个float类型的数值,则需要在其后追加字母F
或f
,如1.111f和1.7F都是float类型的常数。
1 | //float赋初值的方式就这一种,double则有两种 |
注:一个值若需要被看作float,则必须以f
或F
后缓结束,否则会被当作double值。而对于double值来说,d或D后缓都是可选的,甚至无任何后缓也是合法的。
例二:假设从 A 地到 B 地路程为 2348.4 米,那么往返 A 和 B 两地需要走多少米?
1 | public static void main(String[] args) { |
运行结果如下
图2-6 运行结果
可以观察到这样一句代码float total = (float) (lutu * 2);
,如果缺少其中的(float)
,则会报错,这是Java强类型检查的最直接体现。
布尔类型
由所学我们可以知道,C中是无布尔类型的,直到C++的诞生开始有了布尔类型,在C++中布尔类型里的true
和flase
分别等价于数值1
和0
,这与Java也是不同的。
由于Java的强类型检查,boolean类型的变量或者表达式只能是取true
和flase
这两个值中的一个。并且在Java语言中,布尔类型的值不能转换成任何其它数据类型,true
不等价于数值1
,flase
也不等价于数值0
。
下面给出使用boolean类型声明方式:
1 | boolean isable; // 声明 boolean 类型的变量 isable |
字符类型
Java语言中的字符型(char)使用两个字节的Unicode编码表示,它支持世界上所有语言,常通过单引号字符或者整数对char型赋值。
下面代码在 main() 方法中定义两个字符类型的变量,并使之相对应的 ASCII(Unicode)值相加,最后将相加后的结果输出。
1 | public static void main(String[] args) { |
执行结果如图2-7 所示
图2-7 执行结果
在该程序中,a 变量首先被赋值为“A”,字母 A 在 ASCII(和 Unicode)中对应的值为 65。接着又定义了一个类型为 char 的变量 b,赋值为“B”,字母 B 在 ASCII(和 Unicode)中所对应的值为 66。因此相加后得出的结果为 131。
引用数据类型
由图2-4可知,Java的引用数据类型建立在基本数据类型之上,包含了数组、类、接口这三大类,引用数据类型是由用户自定义的,用来限制其它数据的类型。需要注意的是——Java不支持C++中的指针、结构体、联合、枚举类型。
引用类型还有一种特殊的null类型需要注意,所谓引用数据类型就是对一个对象的引用,对象包括实例和数组两种。实际上,引用类型变量就是一个指针,只是 Java 语言里不再使用指针这个说法。
空类型(null type)就是 null 值的类型,这种类型没有名称。因为 null 类型没有名称,所以不可能声明一个 null 类型的变量或者转换到 null 类型。
空引用(null)是 null 类型变量唯一的值。空引用(null)可以转换为任何引用类型。
在实际开发中,程序员可以忽略 null 类型,假定 null 只是引用类型的一个特殊直接量。
注意:空引用(null)只能被转换成引用类型,不能转换成基本类型,因此不要把一个 null 值赋给基本数据类型的变量。
Java数据类型转换
Java的数据类型转换可以分为隐式转换(自动类型转换)和显示转换(强制类型转换)两种。由于和C/C++并无太大区别,这里仅仅简单带一下。
隐式转换(自动类型转换)
满足以下两个条件,则可以在赋值符两侧的数据类型不同时执行自动类型转换(automatic type conversion)。
- 两种数据类型彼此兼容
- 向上转型(低级类型数据转换成高级类型数据)
在运算过程中,不同的数据类型会转换成同一种数据类型,所有整型、浮点型以及字符型都可以参与混合运算,实现向上转型,规则如下:
- 数值型数据的转换:byte→short→int→long→float→double
- 字符型转换为整型:char→int
值得注意的是,自动类型转换在使运算更加方便时也会带来一些令人以获得编译错误,下面给出一个案例:
1 | byte b = 50; |
如上所示,第二行会报“类型不匹配:无法从int转换为byte”错误。
这是因为在经过b * 2
的运算之后,其自动执行了类型转换,byte乘以int的值向上转型为了int,所以此时等式右侧的运算结果为int类型,而左侧为一个byte类型的变量,根据自动类型转换的规则,这是不合法的,因为无法将int类型的值赋值给比它低级的byte类型变量。
所以在此处需要是由一个强制转换,如:
1 | byte b = 50; |
注意:char 类型比较特殊,char 自动转换成 int、long、float 和 double,但 byte 和 short 不能自动转换为 char,而且 char 也不能自动转换为 byte 或 short。
显示转换(强制类型转换)
自动类型转换并不能满足所有编程需要,尤其是在实现由较高级类型转换至较低级类型时,这也就是所谓的“缩小转换”。
所以当两种数据类型不兼容,或目标类型的取值范围小于源类型时,自动转换将无法进行,这时就需要进行强制类型转换。其语法格式如下:
1 | (type)variableName |
一个案例:
1 | int a = 3; |
在强制类型转换中,如果是将浮点类型的值转换为整数,直接去掉小数点后边的所有数字;而如果是整数类型强制转换为浮点类型时,将在小数点后面补零。
Java运算符
算数运算符
算数运算符根据操作数的数量可以分为单目运算符、双目运算符、三目运算符。
一元运算符
运 算 符 | 名 称 | 说 明 | 例 子 |
---|---|---|---|
- | 取反符号 | 取反运算 | b=-a |
++ | 自加一 | 先取值再加一,或先加一再取值 | a++ 或 ++a |
– | 自减一 | 先取值再减一,或先减一再取值 | a– 或 –a |
表2-4 一元算数运算
用法与C/C++一样。
二元运算符
运 算 符 | 名 称 | 说 明 | 例 子 |
---|---|---|---|
+ | 加 | 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 | a + b |
- | 减 | 求 a 减 b 的差 | a - b |
* | 乘 | 求 a 乘以 b 的积 | a * b |
/ | 除 | 求 a 除以 b 的商 | a / b |
% | 取余 | 求 a 除以 b 的余数 | a % b |
表2-5 二元算数运算
算术运算符都是双目运算符,即连接两个操作数的运算符。优先级上,*、/、% 具有相同运算级别,并高于 +、-(+、- 具有相同级别)。
需要注意的点:
①int x=2,y=1; 表达式 y/x 的结果是 0。
②float x=2.0f; int y=1; 表达式 y/x 的结果是 0.5。
案例:
1 | public static void main(String[] args) { |
运行结果:
1 | 整数的算术运算 |
算数赋值运算符
运 算 符 | 名 称 | 例 子 |
---|---|---|
+= | 加赋值 | a += b、a += b+3 |
-= | 减赋值 | a -= b |
*= | 乘赋值 | a *= b |
/= | 除赋值 | a /= b |
%= | 取余赋值 | a %= b |
表2-6 算数赋值运算
使用方法与C/C++相同,不予过述。
赋值运算符
赋值运算符是指为变量或常量指定数值的符号。赋值运算符的符号为“=”,它是双目运算符,左边的操作数必须是变量,不能是常量或表达式。
语法格式:变量名称=表达式内容
逻辑运算符
逻辑运算符是对布尔型变量进行运算,其结果也是布尔型。
运算符 | 用法 | 含义 | 说明 | 实例 | 结果 |
---|---|---|---|---|---|
&& | a&&b | 短路与 | ab 全为 true 时,计算结果为 true,否则为 false。 | 2>1&&3<4 | true |
|| | a||b | 短路或 | ab 全为 false 时,计算结果为 false,否则为 true。 | 2<1||3>4 | false |
! | !a | 逻辑非 | a 为 true 时,值为 false,a 为 false 时,值为 true | !(2>4) | true |
| | a|b | 逻辑或 | ab 全为 false 时,计算结果为 false,否则为 true | 1>2|3>5 | false |
& | a&b | 逻辑与 | ab 全为 true 时,计算结果为 true,否则为 false | 1<2&3<5 | true |
表2-7 逻辑运算符的用法、含义及实例
- && 与 & 区别:如果 a 为 false,则不计算 b(因为不论 b 为何值,结果都为 false)
- || 与 | 区别:如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为 true)
注意:短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或。
逻辑运算符的优先级为:!运算级别最高,&& 运算高于 || 运算。!运算符的优先级高于算术运算符,而 && 和 || 运算则低于关系运算符。结合方向是:逻辑非(单目运算符)具有右结合性,逻辑与和逻辑或(双目运算符)具有左结合性。
关系运算符
运算符 | 含义 | 说明 | 实例 | 结果 |
---|---|---|---|---|
> | 大于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值大于后面变量的值, 则返回 true。 | 2>3 | false |
>= | 大于或等于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值大于等于后面变量的值, 则返回 true。 | 4>=2 | true |
< | 小于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值小于后面变量的值,则返回 true。 | 2<3 | true |
<= | 小于或等于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值小于等于后面变量的值, 则返回 true。 | 4<=2 | false |
== | 相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。Java也支持两个 boolean 类型的值进行比较。 | 4==4 97==’a’ 5.0==5 true==false | true true true false |
!= | 不相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。 | 4!=2 | true |
表2-8 比较运算符的含义及其实例应用
注意点如下所示:
- 基本类型的变量、值不能和引用类型的变量、值使用 == 进行比较;boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较;如果两个引用类型之间没有父子继承关系,那么它们的变量也不能使用 == 进行比较。
- == 和 != 可以应用于基本数据类型和引用类型。当用于引用类型比较时,比较的是两个引用是否指向同一个对象,但当时实际开发过程多数情况下,只是比较对象的内容是否相当,不需要比较是否为同一个对象。
关系运算符的优先级为:>、<、>=、<= 具有相同的优先级,并且高于具有相同优先级的 !=、==。关系运算符的优先级高于赋值运算符而低于算术运算符,结合方向是自左向右。
自增和自减运算符
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
i++ | 将 i 的值先使用再加 1 赋值给 i 变量本身 | int i=1; int j=i++; | i=2 j=1 |
++i | 将 i 的值先加 1 赋值给变量 i 本身后再使用 | int i=1; int j=++i; | i=2 j=2 |
i– | 将 i 的值先使用再减 1 赋值给变量 i 本身 | int i=1; int j=i–; | i=0 j=1 |
–i | 将 i 的值先减 1 后赋值给变量 i 本身再使用 | int i=1; int j=–i; | i=0 j=0 |
表2-9 自增、自减运算的含义及其使用实例
位运算符
Java定义的为玉奴三直接对整数类型的位进行操作,这些整数包括long、int、short、char、byte。
位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值。
Java中的位运算符分为为逻辑运算符和位移运算符两类
位逻辑运算符
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
& | 按位进行与运算(AND) | 4 & 5 | 4 |
| | 按位进行或运算(OR) | 4 | 5 | 5 |
^ | 按位进行异或运算(XOR) | 4 ^ 5 | 1 |
~ | 按位进行取反运算(NOT) | ~ 4 | -5 |
表2-10 位逻辑运算符
按位与:5&12
图2-8 5与12的按位与运算
按位或:11|7
图2-9 11与7的按位或运算
按位异或:11^7
图2-10 11与7的按位异或运算
提示:在有的高级语言中(如Python和Visaul Basic),将运算符^
作为求幂运算符,要注意区分。
按位取反:~10
图2-11 10的按位取反运算
位移运算符
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
» | 右移位运算符 | 8»1 | 4 |
« | 左移位运算符 | 9«2 | 36 |
表2-11 位移运算符
左位移运算符:«
运算规则:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。相当于原数的两倍。
图2-12 11的左位移运算
右位移运算符:»
运算规则:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。相当于原数整除 2 的结果。
图2-13 11的右位移运算
复合位赋值运算符
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
&= | 按位与赋值 | num1 &= num2 | 等价于 num 1=num 1 & num2 |
|= | 按位或赋值 | num1 |= num2 | 等价于 num 1=num 1 | num2 |
^= | 按位异或赋值 | num1 ^= num2 | 等价于 num 1=num 1 ^ num2 |
-= | 按位取反赋值 | num1 -= num2 | 等价于 num 1=num 1 - num2 |
«= | 按位左移赋值 | num1 «= num2 | 等价于 num 1=num 1 « num2 |
»= | 按位右移赋值 | num1 »= num2 | 等价于 num 1=num 1 » num2 |
表2-12 复合位赋值运算符
案例:
1 | int a = 1; |
运行结果:
1 | a = 1 |
条件运算符(三目运算符)
条件运算符的符号表示为“?:”,使用该运算符时需要有三个操作数,因此称其为三目运算符。经常被用来取代if-then-else
语句。下面给出案例:
1 | int x,y,z; |
用法和C/C++一样不过述。直接给出实际案例。
在程序中声明 3 个变量 x、y、z,并由用户从键盘输入 x 的值,然后使用条件运算符向变量 y 和变量 z 赋值。 实现代码如下:
1 | public class Test9 { |
运行结果:
图2-14 键盘输入58
运算符优先级
算术运算符优先级较高,关系和逻辑运算符优先级较低。多数运算符具有左结合性,单目运算符、三目运算符、赋值运算符具有右结合性。
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ()、[]、{} | 从左向右 |
2 | !、+、-、~、++、– | 从右向左 |
3 | *、/、% | 从左向右 |
4 | +、- | 从左向右 |
5 | «、»、>>> | 从左向右 |
6 | <、<=、>、>=、instanceof | 从左向右 |
7 | ==、!= | 从左向右 |
8 | & | 从左向右 |
9 | ^ | 从左向右 |
10 | | | 从左向右 |
11 | && | 从左向右 |
12 | || | 从左向右 |
13 | ?: | 从右向左 |
14 | =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= | 从右向左 |
表2-13 运算符优先级
使用优先级为 1 的小括号可以改变其他运算符的优先级。例如:(x-y)*z/5
提醒:
- 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
- 不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用
()
来控制表达式的执行顺序。
直接量(字面量)
直接量是指在程序中通过源代码直接给出的值。
直接量类型:
1)int 类型的直接量
直接给出的整型数值,可分为二进制(以 0B 或 0b 开头)、十进制、八进制(以 0 开头)和十六进制(以 0x 或 0X 开头) 4 种。例如 123、012(对应十进制的 10)、0x12(对应十进制的 18)等。
2)long 类型的直接量
在整型数值后添加 l 或 L 后就变成了 long 类型的直接量。例如 3L、0x12L(对应十进制的 18L)。
3)float 类型的直接量
在一个浮点数后添加 f 或 F 就变成了 float 类型的直接量,这个浮点数可以是标准小数形式,也可以是科学计数法形式。例如 5.34F、3.14E5f。
4)double 类型的直接量
直接给出一个标准小数形式或者科学计数法形式的浮点数就是 double 类型的直接量。例如 5.34、3.14E5、7.32d、9.83D。
5)boolean 类型的直接量
只有 true 和 false。
6)char 类型的直接量
char 类型的直接量有三种形式,分别是用单引号括起来的字符、转义字符和 Unicode 值表示的字符。例如‘a’,‘\n’和‘\u0061’。
7)String 类型的直接量
一个用双引号括起来的字符序列就是 String 类型的直接量。
在大多数其他语言中,包括 C/C++,字符串作为字符的数组被实现。然而,在 Java 中并非如此。在 Java 中,字符串实际上是对象类型。在教程后面你将看到,因为 Java 对字符串是作为对象实现的,因此,它有广泛的字符串处理能力,而且功能既强又好用。
8)null 类型的直接量
这个类型的直接量只有一个值,即 null。null可以赋给任何引用类型的变量,用以表示这个引用类型变量中保存的地址为空,即还未指向任何有效对象。包括 String 类型。
案例:
1 | int a = 5; |
关于字符串直接量有一点需要指出,当程序第一次使用某个字符串直接量时,Java 会使用常量池(constant pool)来缓存该字符串直接量,如果程序后面的部分需要用到该字符串直接量时,Java 会直接使用常量池(constantpool)中的字符串直接量。
Tips:
- 由于 String 类是一个典型的不可变类,因此 String 对象创建出来的就不可能改变,因此无需担心共享 String 对象会导致混乱。
- 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的 .class 文件中的一些数据,它包括关于类、方法、接口中的常量,也包括字符串直接量。
看以下案例:
1 | String s0 = "hello"; |
运行结果:
1 | true |
“he”和”llo”也都是字符串常量,当一个字符串由多个字符串常量连接而成,它本身也是字符串常量,s2同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”hello”的引用。所以s1 == s2
也返回true。