作者:W_chuanqi
文章目录
- Java编程基础
- 1.Java基本语法
- 1.1 Java程序的基本格式
- 1.2 Java中注释
- 1.2.1.单行注释
- 1.2.2.多行注释
- 1.2.3.文档注释
- 1.3 Java中的标识符
- 1.4 Java中的关键字
- 1.5 Java中的常量
- 1.5.1.整型常量
- 1.5.2.浮点数常量
- 1.5.3.字符常量
- 1.5.4.字符串常量
- 1.5.5.布尔常量
- 1.5.6.null常量
- 1.5.7.声明常量
- 2.变量的定义和使用
- 2.1 变量的定义
- 2.2 变量的数据类型
- 2.2.1.整数类型变量
- 2.2.2.浮点数类型变量
- 2.2.3.字符类型变量
- 2.2.4.布尔类型变量
- 2.3 变量的类型转换
- 2.3.1.自动类型转换
- 2.3.2.强制类型转换
- 2.4 变量的作用域
- 3.运算符
- 3.1 算术运算符
- 3.2 赋值运算符
- 3.3 比较运算符
- 3.4 逻辑运算符
- 3.5 位运算符
- 3.6 三元运算符
- 3.7 运算符优先级
Java编程基础
1.Java基本语法
1.1 Java程序的基本格式
Java程序代码必须放在一个类中,初学者可以简单地把一个类理解为一个Java程序。类使用class关键字定义,在class前面可以有类的修饰符,类的定义格式如下:
修饰符 class 类名{
程序代码
}
(1)Java程序代码可分为结构定义语句和功能执行语句,其中,结构定义语句用于声明一个类或方法,功能执行语句用于实现具体的功能。每条功能执行语句的最后必须用分号(;)结束。如下面的语句:
System.out.println("这是第一个Java程序!");
需要注意的是,在程序中不要将英文的分号(;)误写成中文的分号(;),如果写成中文的分号,编译器会报告 “illegal character”(非法字符)错误信息。(老生常谈)
(2)Java语言是严格区分大小写的。在定义类时,不能将class写成Class,否则编译器会报错。程序中定义一个computer的同时,还可以定义一个Computer,computer和Computer是两个完全不同的符号,在使用时务必注意。
(3)虽然Java没有严格要求用什么样的格式编排程序代码,但是,出于可读性的考虑,应该让自己编写的程序代码整齐美观、层次清晰。常用的编排方式是一行只写一条语句,符号“{”与语句同行,符号“}”独占一行,示例代码如下:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("这是第一个Java程序!");
}
}
(4)Java程序中一个连续的字符串不能分成两行书写。例如,下面这条语句在编译时将会出错:
System.out.println("这是第一个
Java程序!");
如果为了便于阅读,需要将一个比较长的字符串分两行书写,可以先将字符串分成两个字符串,然后用加号(+)将这两个字符串连起来,在加号(+)处换行。例如,可以将上面的语句可以修改成如下形式:
System.out.println("这是第一个" +
"Java程序!");
1.2 Java中注释
1.2.1.单行注释
单行注释用于对程序中的某一行代码进行解释,一般用来注释局部变量。单行注释用符号“//”表示,“//”后面为被注释的内容,具体示例如下:
int c = 10; // 定义一个整型变量
1.2.2.多行注释
多行注释顾名思义就是注释的内容可以为多行,它以符号“/”开头,以符号“/”结尾。多行注释具体示例如下:
/* int c = 10;
int x = 5; */
1.2.3.文档注释
文档注释是以“/**”开头,并在注释内容末尾以“*/”结束。文档注释是对一段代码概括性的解释说明,可以使用javadoc命令将文档注释提取出来生成帮助文档。文档注释具体示例如下:
/**
name = “黑马程序员”;
*/
1.3 Java中的标识符
在编程过程中,经常需要在程序中定义一些符号标记一些名称,如包名、类名、方法名、参数名、变量名等,这些符号被称为标识符。标识符可以由字母、数字、下画线(_)和美元符号($)组成,但标识符不能以数字开头,不能是Java中的关键字。
//合法标识符
username
username123
user_name
userName
$username
//不合法标识符
123username
class
98.3
为了增强代码的可读性,建议在定义标识符时还应该遵循以下规则:
- (1)包名所有字母一律小写。例如:cn.itcast.test。
- (2)类名和接口名每个单词的首字母都要大写。例如:ArrayList、Iterator。
- (3)常量名所有字母都大写,单词之间用下划线连接。例如:DAY_OF_MONTH。
- (4)变量名和方法名的第一个单词首字母小写,从第二个单词开始每个单词首字母大写。例如:lineNumber、getLineNumber。
- (5)在程序中,应该尽量使用有意义的英文单词定义标识符,使得程序便于阅读。例如,使用userName定义用户名,password定义密码。
1.4 Java中的关键字
Java中的关键字
关键字 | 说明 |
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 布尔类型 |
break | 跳出语句,提前跳出一块代码 |
byte | 字节类型 |
case | 用在 switch 语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 字符类型 |
class | 用于声明类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,如在 switch 语句中表示默认分支 |
do | do… while 循环结构使用的关键字 |
double | 双精度浮点类型 |
else | 用在条件语句中,表明当条件不成立时的分支 |
enum | 用于声明枚举 |
extends | 用于创建继承关系 |
final | 用于声明不可改变的最终属性,如常量 |
finally | 声明异常处理语句中始终会被执行的代码块 |
float | 单精度浮点类型 |
for | for 循环语句关键字 |
goto | 保留关键字,没有具体含义 |
if | 条件判断语句关键字 |
implements | 用于创建类与接口的实现关系 |
import | 导入语句 |
instanceof | 判断两个类的继承关系 |
int | 整数类型 |
interface | 用于声明接口 |
long | 长整数类型 |
native | 用于声明一个方法是由与计算机相关的语言(如 C/C+/FORTRAN 语言)实现的 |
new | 用于创建新实例对象 |
package | 包语句 |
private | 私有权限修饰符 |
protected | 受保护权限修饰符 |
public | 公有权限修饰符 |
return | 返回方法结果 |
short | 短整数类型 |
static | 静态修饰符 |
strictfp | 用于声明 FP_strict(单精度或双精度浮点数)表达式遵循 IEEE 754 算术标准 |
super | 父类对象 |
switch | 分支结构语句关键字 |
synchronized | 线程同步关键字 |
this | 本类对象 |
throw | 抛出异常 |
throws | 方法将异常处理抛向外部方法 |
transient | 声明不用序列化的成员域 |
try | 尝试监控可能抛出异常的代码块 |
var | 声明局部变量 |
void | 表明方法无返回值 |
volatile | 表明两个或多个变量必须同步发生变化 |
while | while 循环语句关键字 |
编写Java程序时,需要注意以下几点:
- (1)所有的关键字都是小写的。
- (2)不能使用关键字命名标识符。
- (3)const和goto是保留字关键字,虽然在Java中还没有任何意义,但在程序中不能用来作为自定义的标识符。
- (4)true、false和null虽然不属于关键字,但它们具有特殊的意义,也不能作为标识符使用。
1.5 Java中的常量
常量就是在程序中固定不变的值,是不能改变的数据。例如,数字1、字符’a’、浮点数3.2等都是常量。在Java中,常量包括整型常量、浮点数常量、布尔常量、字符常量等。
1.5.1.整型常量
整型常量是整数类型的数据,有二进制、八进制、十进制和十六进制4种表示形式。
- 二进制:由数字0和1组成的数字序列。从JDK7开始,允许使用字面值表示二进制数,前面要以0b或0B开头,目的是为了和十进制进行区分,如0b01101100、0B10110101。
- 八进制:以0开头并且其后由0~7范围内(包括0和7)的整数组成的数字序列,如0342。
- 十进制:由数字0~9范围内(包括0和9)的整数组成的数字序列,如198。
- 十六进制:以0x或者0X开头并且其后由0~9、A~F(包括0和9、A和F,字母不区分大小写)组成的数字序列,如0x25AF。
在程序中为了标明不同的进制,数据都有特定的标识,八进制必须以0开头,如0711、0123;十六进制必须以0x或0X开头,如0xaf3、0Xff;整数以十进制表示时,第一位不能是0。例如,十进制的127,用二进制表示为0b1111111或者0B1111111,用八进制表示为0177,用十六进制表示为0x7F或者0X7F。
多学一招:十进制和二进制之间的转换
1.十进制转二进制
十进制转换成二进制就是一个除以2取余数的过程。把要转换的数,除以2,得到商和余数,将商继续除以2,直到商为0。最后将所有余数倒序排列,得到的数就是转换结果。
十进制数据6三次除以2得到的余数依次是0、1、1,将所有余数倒序排列是110,所以十进制的6转换成二进制,结果是110。
2.二进制转十进制
二进制转化成十进制要从右到左用二进制位上的每个数乘以2的相应次方。例如,将最右边第一位的数乘以2的0次方,第二位的数乘以2的1次方,第n位的数乘以2的n-1次方,然后把所有相乘后的结果相加,得到的结果就是转换后的十进制。
例如,把二进制数0110 0100转换为十进制,转换方式如下:
0 * 20+ 0 * 21 + 1 * 22 + 0 * 23 + 0 * 24 + 1 * 25+ 1 * 26+ 0 * 27 = 100
得到的结果100就是二进制数0110 0100转化后的十进制数。
1.5.2.浮点数常量
浮点数常量就是在数学中用到的小数,浮点数分为单精度浮点数(float)和双精度浮点数(double)两种类型。
其中,单精度浮点数后面以F或f结尾,而双精度浮点数则以D或d结尾。当然,在使用浮点数时也可以在结尾处不加任何的后缀,此时JVM会默认浮点数为double类型的浮点数。浮点数常量还可以通过指数形式表示。
1.5.3.字符常量
字符常量用于表示一个字符,一个字符常量要用一对**英文半角格式的单引号(‘’)**括起来。字符常量可以是英文字母、数字、标点符号、以及由转义序列表示的特殊字符。
//字符常量
'a'
'1'
'&'
'\r'
'\u0000'
1.5.4.字符串常量
字符串常量用于表示一串连续的字符,一个字符串常量要用一对**英文半角格式的双引号(“ ”)**括起来。
//字符串
"HelloWorld"
"123"
"Welcome \n XXX"
""
1.5.5.布尔常量
布尔常量即布尔型的值,用于区分事物的真与假。布尔常量有true和false两个值。
1.5.6.null常量
null常量只有一个值null,表示对象的引用为空。
1.5.7.声明常量
在 Java 中,利用关键字 final 指示常量。例如:
public class Constants
{
public static void main(String[] args)
{
final double CM_PER_INCH = 2.54;
double paperwidth = 8.5;
double paperHeight = 11;
System.out.println("Paper size in centimeters:"+ paperwidth * CM_ PER_ INCH +" by "+ paperHeight * CM_PER_INCH);
}
}
关键字 final 表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。
在 Java中,经常希望某个常量可以在一个类的多个方法中使用,通常将这些常量称为类常量(class constant)。可以使用关键字 static final 设置一个类常量。下面是使用类常量的示例:
public class Constants2
{
public static final double CM_PER_INCH = 2.54;
public static void main(stringl] args)
{
double paperwidth = 8.5;
double paperHeight = 11;
System.out. println("Paper size in centimeters:"+ paperwidth * CM PER_INCH +" by "+ paperHeight * CM_PER_INCH);
}
}
需要注意,类常量的定义位于main方法的外部。因此,在同一个类的其他方法中也可以使用这个常量。而且,如果一个常量被声明为public,那么其他类的方法也可以使用这个常量。
2.变量的定义和使用
2.1 变量的定义
在程序运行期间,随时可能产生一些临时数据,应用程序会将这些数据保存在内存单元中,每个内存单元都用一个标识符标识,这些用于标识内存单元的标识符就称为变量,内存单元中存储的数据就是变量的值。
通过具体的代码学习变量的定义。
int x = 0,y;
y = x+3;
上面的代码中,第一行代码定义了两个变量x和y,也就相当于分配了两块内存单元,在定义变量的同时为变量x分配了一个初始值0,而变量y没有分配初始值,变量x和y在内存中的状态如下图。
第二行代码的作用是为变量赋值,在执行第二行代码时,程序首先取出变量x的值,与3相加后,将结果赋值给变量y,此时变量x和y在内存中的状态发生了变化,如下图。
2.2 变量的数据类型
Java中的所有数据类型如下图。
2.2.1.整数类型变量
整数类型变量用来存储整数数值,即没有小数部分的值。在Java中,为了给不同大小范围内的整数合理地分配存储空间,整数类型分为4种不同的类型,分别是字节型(byte)、短整型(short)、整型(int)和长整型(long)。
类型 | 占用空间 | 取值范围 |
byte | 8位(1个字节) | -128~127 |
short | 16位(2个字节) | -32768~32767 |
int | 32位(4个字节) | -2147483648~2147483647(刚刚超过20亿) |
long | 64位(8个字节) | -9223372036854775808~9223372036854775807 |
注意:
在为一个long类型的变量赋值时,所赋值的后面要加上字母L(或小写l),说明赋值为long类型。如果赋的值未超出int型的取值范围,则可以省略字母L(或小写l)。
//示例:
long num = 2200000000L; // 所赋的值超出了int型的取值范围,后面必须加上字母L
long num = 198L; // 所赋的值未超出int型的取值范围,后面可以加上字母L
long num = 198; // 所赋的值未超出int型的取值范围,后面可以省略字母L
2.2.2.浮点数类型变量
浮点数类型变量用于存储小数数值。double类型所表示的浮点数比float类型更精确,两种浮点数所占存储空间的大小以及取值范围。
类型名 | 占用空间 | 取值范围 |
float | 32位(4个字节) | 1.4E-45 ~ 3.4E+38 |
double | 64位(8个字节) | 4.9E-324 ~ 1.7E+308 |
在Java中,一个小数会被默认为double类型的值,因此在为一个float类型的变量赋值时,在所赋值的后面一定要加上字母F(或者小写f),而为double类型的变量赋值时,可以在所赋值的后面加上字母D(或小写d),也可以不加。
所有的浮点数值计算都遵循 IEEE 754 规范。具体来说,下面是用于表示溢出和出错情况的三个特殊的浮点数值:
- 正无穷大
- 负无穷大
- NaN (不是一个数字)
例如,一个正整数除以 0 的结果为正无穷大。计算 0/0 或者负数的平方根结果为 NaN。
📄注释:常量 Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY和 Double.NaN(以及相应的Float 类型的常量)分别表示这三个特殊的值,但在实际应用中很少遇到。特别要说明的是,不能如下检测一个特定值是否等于 Double.NaN:
if(x == Double.NaN)// is never true
所有“非数值”的值都认为是不相同的。不过,可以如下使用 Double.isNaN方法来判断:
if (Double.isMaN(x))// check whether x is "not a number"
❗警告:浮点数值不适用于无法接受舍入误差的金融计算。例如,命令 System.out.println(2.0-1.1)将打印出 0.8999999999999999,而不是人们期望的 0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3 一样。
//示例:
float f = 123.4f; // 为一个float类型的变量赋值,后面必须加上字母f
double d1 = 100.1; // 为一个double类型的变量赋值,后面可以省略字母d
double d2 = 199.3d; // 为一个double类型的变量赋值,后面可以加上字母d
在程序中也可以为一个浮点数类型变量赋予一个整数数值。
float f = 100; // 声明一个float类型的变量并赋整数值
double d = 100; // 声明一个double类型的变量并赋整数值
2.2.3.字符类型变量
在Java中,字符类型变量用char表示,用于存储一个单一字符。Java中每个char类型的字符变量都会占用2个字节。在给char类型的变量赋值时,需要用一对英文半角格式的单引号(’ ‘)把字符括起来,如’a’。
在计算机的世界里,所有文字、数值都只是一连串的0与1,这些0与1是机器语言,人类难以理解,于是就产生了各种方式的编码,使用一个数值代表某个字符,如常用的字符编码系统ASCII。
Java使用Unicode字符码系统,Unicode为每个字符制定了一个唯一的数值,在计算时,计算机会自动将字符转化为所对应的数值,如用97表示小写英文字母a。
char c = 'a'; // 为一个char类型的变量赋值字符a
char ch = 97; // 为一个char类型的变量赋值整数97,相当于赋值字符a
转义字符
转义字符是一种特殊的字符变量,它以反斜杠“\”开头,后跟一个或多个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”。例如,printf 函数的格式串中用到的“\n”就是一个转义字符,意思是“回车换行”。Java 中的转义字符如下表所示。转义字符含义\ddd1~3 位八进制数据所表示的字符,如\123\uxxxx4 位十六进制数据所表示的字符,如\u0052\’单引号字符\\反斜杠字符\t垂直制表符,将光标移到下一个制表符的位置\r回车\n换行\b退格\f换页
将转义字符赋值给字符变量时,与字符常量值一样需要使用单引号。
2.2.4.布尔类型变量
在Java中,使用boolean定义布尔类型变量,布尔类型变量只有true和false两个值。定义布尔类型变量,具体示例如下:
boolean flag = false; // 定义一个boolean类型的变量flag,初始值为false
flag = true; // 改变变量flag的值为true
整型值与布尔值之间不能进行相互转换。
2.3 变量的类型转换
2.3.1.自动类型转换
自动类型转换也叫隐式类型转换,指的是两种数据类型在转换的过程中不需要显式地进行声明,由编译器自动完成。自动类型转换必须同时满足两个条件,第一是两种数据类型彼此兼容,第二是目标类型的取值范围大于源类型的取值范围。
在上图中实线箭头,表示无信息丢失的转换;虚线箭头,表示可能有精度损失的转换。例如,123 456 789 是一个大整数,它所包含的位数比 float 类型所能够表示的位数多。当将这个整数转换为 float 类型时,将会得到正确的大小,但是会损失一些精度。
int n = 123456789;
float f = n;//f is 1.23456792E8
当用一个二元运算符连接两个值时(例如 n+ f,n 是整数,f 是浮点数),先要将两个操作数转预为同一种爽型,然后再进行计算。
- 如果两个操作数中有一个是 double 类型,另一个操作数就会转换为 double 类型。
- 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
- 否则,如果其中一个操作数是 long 类型,另一个操作数将会转换为 long 类型。
- 否则,两个操作数都将被转换为 int 类型。
2.3.2.强制类型转换
强制类型转换也叫显式类型转换,指的是两种数据类型之间的转换需要进行显式地声明。当两种类型彼此不兼容,或者目标类型取值范围小于源类型时,自动类型转换无法进行,这时就需要进行强制类型转换。
public class Example01 {
public static void main(String[] args) {
int num = 4;
byte b = num;
System.out.println(b);
}
}
编译上述代码,程序报错。错误原因:数据类型不兼容,不能将int类型转换成byte类型。
解决办法:进行强制类型转换,即强制将int类型的值赋值给byte类型的变量。
强制类型转换格式:目标类型 变量 = (目标类型)值
将变量num赋值给变量b时,进行强制类型转换,代码如下:
public class Example01 {
public static void main(String[] args) {
int num = 4;
byte b = (byte)num;
System.out.println(b);
}
}
警告:如果试图将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值。例如,(byte) 300 的实际值为44。
public class Example02 {
public static void main(String[] args) {
byte a; // 定义byte类型的变量a
int b = 298; // 定义int类型的变量b
a = (byte) b;
System.out.println("b=" + b);
System.out.println("a=" + a);
}
}
上述程序运行结果如下图。
从运行结果可知变量b本身的值为298,然而在赋值给变量a后,a的值为42。原因:变量b为int类型,在内存中占用4个字节;byte类型的数据在内存中占用1个字节,当将变量b的类型强转为byte类型后,前面3个高位字节的数据丢失,数值发生改变。
多学一招:表达式类型自动提升
所谓表达式是指由变量和运算符组成的一个算式。变量在表达式中进行运算时,可能发生自动类型转换,这就是表达式数据类型的自动提升。例如,一个byte型的变量在运算期间类型会自动提升为int型。
public class Example03 {
public static void main(String[] args) {
byte b1 = 3; // 定义一个byte类型的变量
byte b2 = 4;
// 两个byte类型变量相加,赋值给一个byte类型变量
byte b3 = b1 + b2;
System.out.println("b3=" + b3);
}
}
编译上述代码,程序报错,原因:表达式b1+b2运算期间,变量b1和b2都被自动提升为int型,表达式的运算结果也就成了int型,将该结果赋给byte型的变量,编译器报错。
解决办法:进行强制类型转换。
byte b3 = (byte) (b1 + b2);
2.4 变量的作用域
变量需要先定义后使用,但这并不意味着定义的变量,在之后所有语句中都可以使用。变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域。在程序中,变量一定会被定义在某一对大括号中,该大括号所包含的代码区域便是这个变量的作用域。
上图中的代码有两层大括号。其中,外层大括号所标识的代码区域就是变量x的作用域,内层大括号所标识的代码区域就是变量y的作用域。
接下来通过一个案例进一步熟悉变量的作用域。
public class Example04 {
public static void main(String[] args) {
int x = 12; // 定义了变量x
{
int y = 96; // 定义了变量y
System.out.println("x is " + x); // 访问变量x
System.out.println("y is " + y); // 访问变量y
}
y = x; // 访问变量x,为变量y赋值
System.out.println("x is " + x); // 访问变量x
}
}
编译上述代码,程序报错,原因:变量y在作用域范围之外被使用(y=x;)。
3.运算符
在程序中经常出现一些特殊符号,如+、-、*、=、>等,这些特殊符号称作运算符。运算符用于对数据进行算术运算、赋值运算和比较运算等。在Java中,运算符可分为算术运算符、赋值运算符、比较运算符、逻辑运算符等。
3.1 算术运算符
在数学运算中最常见的就是加减乘除,被称作四则运算。Java中的算术运算符就是用来处理四则运算的符号,算术运算符是最简单、最常用的运算符号。
运算符 | 运算 | 范例 | 结果 |
+ | 正号 | +3 | 3 |
- | 负号 | b=4;-b; | -4 |
+ | 加 | 5+5 | 10 |
- | 减 | 6-4 | 2 |
* | 乘 | 3*4 | 12 |
/ | 除 | 5/5 | 1 |
% | 取模(即算术中的求余数) | 7%5 | 2 |
++ | 自增(前) | a=2;b=++a; | a=3;b=3; |
++ | 自增(后) | a=2;b=a++; | a=3;b=2; |
– | 自减(前) | a=2;b=–a | a=1;b=1; |
– | 自减(后) | a=2;b=a– | a=1;b=2; |
算术运算符在使用时需要注意的问题:
(1)在进行自增(++)和自减(–)运算时,如果运算符++或–放在操作数的前面,则先进行自增或自减运算,再进行其他运算。反之,如果运算符放在操作数的后面,则先进行其他运算再进行自增或自减运算。
int a = 1;
int b = 2;
int x = a + b++;
System.out.print("b=" b);//print方法不在输出后增加换行符
System.out.print("x=" x);
运行结果为:b=3、x=3。 在上述代码中,定义了三个int类型的变量a、b、x。其中a=1、b=2。当进行“a+b++”运算时,由于运算符++写在了变量b的后面,则先进行a+b运算,再进行变量b的自增,因此变量b在参与加法运算时其值仍然为2,x的值应为3。变量b在参与运算之后会进行自增,因此b的最终值为3。
(2)在进行除法运算时,当除数和被除数都为整数时,得到的结果也是一个整数。如果除法运算有小数参与,得到的结果会是一个小数。例如,2510/1000属于整数之间相除,会忽略小数部分,得到的结果是2,而2.5/10的结果为0.25。
(3)在进行取模(%)运算时,运算结果的正负取决于被模数(%左边的数)的符号,与模数(%右边的数)的符号无关。例如,(-5)%3=-2,而5%(-3)=2。
3.2 赋值运算符
赋值运算符的作用就是将常量、变量或表达式的值赋给某一个变量。
运算符 | 运算 | 范例 | 结果 |
= | 赋值 | a=3;b=2; | a=3;b=2; |
+= | 加等于 | a=3;b=2;a+=b; | a=5;b=2; |
-= | 减等于 | a=3;b=2;a-=b; | a=1;b=2; |
*= | 乘等于 | a=3;b=2;a*=b; | a=6;b=2; |
/= | 除等于 | a=3;b=2;a/=b; | a=1;b=2; |
%= | 模等于 | a=3;b=2;a%=b; | a=1;b=2; |
&= | 与结果赋予左侧 | a &= b; | a = a & b; |
|= | 或结果赋予左侧 | a |= b; | a = a | b; |
^= | 异或结果赋予左侧 | a ^= b; | a = a ^ b; |
<<= | 左移结果赋予左侧 | a <<= b; | a = a << b; |
>>= | 右移结果赋予左侧 | a >>= b; | a = a >> b; |
>>>= | 无符号右移结果赋予左侧 | a >>>= b; | a = a >>> b; |
赋值运算符使用时的注意事项。
(1)在Java中可以通过一条赋值语句对多个变量进行赋值,具体示例如下:
int x, y, z;
x = y = z = 5; // 为三个变量同时赋值
在上述代码中,一条赋值语句将变量x,y,z的值同时赋值为5。需要注意的是,下面的这种写法在Java中是不可以的。
int x = y = z = 5; // 这样写是错误的
(2)在上表中,除了“=”,其他的都是特殊的赋值运算符,以“+=”为例,x += 3就相当于x = x + 3,表达式首先会进行加法运算x+3,再将运算结果赋值给变量x。-=、*=、/=、%=赋值运算符都可以此类推。
多学一招:强制类型转换
在为变量赋值时,当两种类型彼此不兼容,或者目标类型取值范围小于源类型时,需要进行强制类型转换。例如,将一个int类型的值赋给一个short类型的变量,需要进行强制类型转换。然而在使用+=、-=、*=、/=、%= 运算符进行赋值时,强制类型转换会自动完成,程序不需要做任何显式地声明。
public class Example05 {
public static void main(String[] args) {
short s = 3;
int i = 5;
s += i; //强制类型转换自动完成
System.out.println("s = " + s);
}
}
3.3 比较运算符
比较运算符用于对两个数值或变量进行比较,比较运算结果是一个布尔值,即true或false。
运算符 | 运算 | 范例 | 结果 |
== | 相等于 | 4 == 3 | false |
!= | 不等于 | 4 != 3 | true |
< | 小于 | 4 < 3 | false |
> | 大于 | 4 > 3 | true |
<= | 小于等于 | 4 <= 3 | false |
>= | 大于等于 | 4 >= 3 | true |
注意:在比较运算中,不能将比较运算符“==”误写成赋值运算符“=”。
3.4 逻辑运算符
逻辑运算符用于对布尔型的数据进行操作,其结果仍是一个布尔值。
运算符 | 运算 | 范例 | 结果 |
& | 与 | true & true true & false false & false false &true | true false false false |
| | 或 | true | true true | false false | false false | true | true true false true |
^ | 异或 | true ^ true true ^ false false ^ false false ^ true | false true false true |
! | 非 | !true !false | false true |
&& | 短路与 | true && true true && false false && false false && true | true false false false |
|| | 短路或 | true || true true || false false || false false || true | true true false true |
使用逻辑运算符需要注意的问题。
(1)逻辑运算符可以针对结果为布尔值的表达式进行运算。例如,x > 3 && y != 0。
(2)运算符“&”和“&&”都表示与操作,当且仅当运算符两边的操作数都为true时,其结果才为true,否则结果为false。虽然运算符“&”和“&&”都表示与操作,但两者在使用上还有一定的区别。在使用“&”进行运算时,不论左边为true或者false,右边的表达式都会进行运算。在使用“&&”进行运算,当左边为false时,右边的表达式就不再进行运算,因此“&&”被称作短路与。
public class Example06 {
public static void main(String[] args) {
int x = 0; // 定义变量x,初始值为0
int y = 0; // 定义变量y,初始值为0
int z = 0; // 定义变量z,初始值为0
boolean a, b; // 定义boolean变量a和b
a = x > 0 & y++ > 1; // 逻辑运算符&对表达式进行运算
System.out.println(a);
System.out.println("y = " + y);
b = x > 0 && z++ > 1; // 逻辑运算符&&对表达式进行运算
System.out.println(b);
System.out.println("z = " + z);
}
}
上述代码中,第3~5行代码定义了三个整型变量x、y、z,初始值都为0;第6行代码定义了两个布尔类型的变量a和b。第7行代码使用“&”运算符对两个表达式进行逻辑运算,左边表达式x>0的结果为false,这时无论右边表达式y++>1的比较结果是什么,整个表达式x > 0 & y++ > 1的结果都会是false。由于使用的是运算符“&”,运算符两边的表达式都会进行运算,因此变量y会进行自增,整个表达式运算结束之后,y的值为1。
第10行代码是逻辑“&&”运算,运算结果和第7行代码一样为false,区别在于,第10行代码使用了短路与“&&”运算符,当左边为false时,右边的表达式不进行运算,因此变量z的值仍为0。
(3)运算符“|”和“||”都表示或操作,当运算符两边的任一表达式值为true时,其结果为true。只有两边表达式的值都为false时,其结果才为false。同逻辑与操作类似,“||”运算符为短路或,当运算符“||”的左边为true时,右边的表达式不再进行运算。
int x = 0;
int y = 0;
boolean b = x==0 || y++>0
上面的代码块执行完毕后,b的值为true,y的值仍为0。原因是运算符“||”的左边表达式x==0结果为true,那么右边表达式将不进行运算,y的值不发生任何变化。
(4)运算符“^”表示异或操作,当运算符两边的布尔值相同时(都为true或都为false),其结果为false。当两边表达式的布尔值不相同时,其结果为true。
3.5 位运算符
位逻辑运算符
运算符 | 含义 | 举例 |
& | 与 | a & b |
| | 或 | a | b |
~ | 取反 | ~a |
^ | 异或 | a ^ b |
位与运算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eyGVqanu-1657459544935)(https://s2.loli.net/2022/07/10/fjceuKsVAwiCGdt.png)]
位或运算
位异或运算
位取反运算
位移运算符
- 左移就是将运算符左边的操作数的二进制数据,按照运算符右边操作数指定的位数向左移动,右边移空的部分补 0。
- 右移则复杂一些。当使用“>>”符号时,如果最高位是 0,有移空的位就填入0;如果最高位是 1,右移空的位就填入 1。
- Java还提供了无符号右移“>>>”,无论最高位是0还是1,左侧被移空的高位都填入0。
运算符 | 含义 | 举例 |
<< | 左移位 | a << 2 |
>> | 右移位 | b >> 4 |
>>> | 无符号右移位 | x >>> 2 |
位移运算
3.6 三元运算符
三元运算符的使用格式为:
条件式?值1:值2
三元运算符的运算规则为:若条件式的值为 true,则整个表达式取值 1,否则取值 2。例如:
boolean b= 20<45 ?true :false;
上述程序表达式“20 <45”的运算结果返回真,那么 boolean 型变量 b 取值为 true。相反,如果表达式的运算结果返回为假,则 boolean 型变量 b 取值为 false。
三元运算符等价于 if…else 语句,例如上述代码等价于:
boolean a;//声明 boolean 型变量
if(20<45)//将 20 < 45 作为判断条件
a = true;//条件成立,将 true 赋值给 a
else
a = false;//条件不成立,将 false 赋值给 a
3.7 运算符优先级
在对一些比较复杂的表达式进行运算时,要明确表达式中所有运算符参与运算的先后顺序,通常把这种顺序称作运算符的优先级。
优先级 | 运算符 |
1 | . [] () |
2 | ++ – ~ ! (数据类型) |
3 | * / % |
4 | + - |
5 | << >> >>> |
6 | < > <= >= |
7 | == != |
8 | & |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ?: |
14 | = *= /= %= += -= <<= >>= >>>= &= ^= |= |
在上表中,运算符前面的数字越小优先级越高。根据运算符优先级,分析下面代码的运行结果。
int a =2;
int b = a + 3*a;
System.out.println(b);
上述代码运行结果为8,由于运算符“*”的优先级高于运算符“+”,因此先运算3*a,得到的结果是6,再将6与a相加,得到最后的结果8。
int a =2;
int b = (a+3) * a;
System.out.println(b);
上述代码运行结果为10,由于运算符“()”的优先级最高,因此先运算括号内的a+3,得到的结果是5,再将5与a相乘,得到最后的结果10。
| < > <= >= |
| 7 | == != |
| 8 | & |
| 9 | ^ |
| 10 | | |
| 11 | && |
| 12 | || |
| 13 | ?: |
| 14 | = *= /= %= += -= <<= >>= >>>= &= ^= |= |
在上表中,运算符前面的数字越小优先级越高。根据运算符优先级,分析下面代码的运行结果。
int a =2;
int b = a + 3*a;
System.out.println(b);
上述代码运行结果为8,由于运算符“*”的优先级高于运算符“+”,因此先运算3*a,得到的结果是6,再将6与a相加,得到最后的结果8。
int a =2;
int b = (a+3) * a;
System.out.println(b);
上述代码运行结果为10,由于运算符“()”的优先级最高,因此先运算括号内的a+3,得到的结果是5,再将5与a相乘,得到最后的结果10。