1 Java运算符
Java世界中的运算其实就是数学运算,而运算符就是其中的媒介。
算术运算符
操作符 | 描述 |
+ | 加法,对符号两边的数值相加 |
– | 减法,符号左边的数减去右边的数 |
* | 乘法,符号两边的数值相乘 |
/ | 除法,符号左边的数除以右边的数 |
% | 取模,符号左边的数除以右边的数所得的余数 |
++ | 自增,操作数的值加1 |
— | 自减,操作数的值减1 |
下面简单的例子演示算术运算符:
public class MyFirst { public static void main(String[] args) { int a = 10; int b = 5; int c = 12; int d = 12; int e = 20; int f = 20; int r1 = a + b;// 10加5,r1输出 15 System.out.println(r1); int r2 = a - b;// 10减5,r2输出 5 System.out.println(r2); int r3 = a * b;// 10乘以5,r3输出 50 System.out.println(r3); int r4 = a / b;// 10除以5,r4输出 2 System.out.println(r4); int r5 = c % b;// 12除以5求余,r5输出 2 System.out.println(r5); int r6 = ++c;// 自增符号在数字前面,则先自增后赋值,r6输出 13 int r7 = d++;// 自增符号在数字后面,则先赋值后自增,r7输出 12 System.out.println(r6); System.out.println(r7); int r8 = --e;// 自减符号在数字前面,则先自减后赋值,r6输出 19 int r9 = f--;// 自减符号在数字后面,则先赋值后自减,r7输出 20 System.out.println(r8); System.out.println(r9); } }
关系运算符
运算符 | 描述 |
== | 检查左右两边的操作数是否相等 |
!= | 检查左右两边的操作数是否不相等 |
> | 检查左边操作数是否大于右边操作数 |
< | 检查左边操作数是否小于右边操作数 |
>= | 检查左边操作数是否大于或等于右边操作数 |
<= | 检查左边操作数是否小于或等于右边操作数 |
下面简单的例子演示关系运算符:
public class MyFirst { public static void main(String[] args) { int a = 5; int b = 5; int c = 12; int d = 20; System.out.println(a == b);// 若a和b相等则表示真(true),输出 true System.out.println(a != b);// 若a和b不相等则表示真(true),输出 false System.out.println(c > d);// 若c大于d则表示真(true),输出 false System.out.println(c < d);// 若c小于d则表示真(true),输出 true System.out.println(a >= b);// 若a大于或等于b则表示真(true),输出 true System.out.println(a <= c);// 若a小于或等于c则表示真(true),输出 true } }
位运算符
Java定义的位运算符,主要应用于整数型(int)、长整数型(long)、短整数型(short)、字符型(char)和字节型(byte)。现在跟大家复习下位运算的一些基础知识,位运算符是作用在其二进制的所有位上,并且按位运算。
计算机的符号数有三种表示方法,分别是原码、反码和补码。
原码,符号位加上真值的绝对值,即用第一位表示符号位(0为正数,1为负数),其余位表示值。
如8位二进制数, +1 = 0000 0001 , -1 = 1000 0001 。原码是人脑最容易理解和计算的表示方式。
反码,正数的反码是其本身,而负数的反码是在其原码的基础上,符号位不变,其他位取反。
如8位二进制数, +1 = 0000 0001(原码)= 0000 0001(反码) , -1 = 1000 0001(原码) = 1111 1110(反码) 。如此可见,负数的反码是人脑无法直观的看出它们的数值的,需要先转回原码才能计算。
补码,正数的补码是其本身,而负数的补码是在其原码的基础上,符号位不变,其他位取反,最后+1,即在其反码的基础上+1。
如8位二进制数, +1 = 0000 0001(原码)= 0000 0001(反码) = 0000 0001(补码) , -1 = 1000 0001(原码) = 1111 1110(反码) = 1111 1111(补码) 。如此可见,负数的补码也是人脑无法直观的计算的它们数值的,需要先转为反码再转为原码计算。
操作符 | 描述 |
& | 如果相对应位都是1,则结果为1,否则为0。 |
| | 如果相对应位都是0,则结果为0,否则为1。 |
^ | 如果相对应位值相同,则结果为0,否则为1。 |
~ | 按位补运算符翻转操作数的每一位,即0变成1,1变成0。 |
<< | 按位左移运算符,左操作数按位左移右操作数指定的位数。 |
>> | 按位右移运算符,左操作数按位右移右操作数指定的位数。 |
>>> | 按位右移补零操作符,左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 |
例如, a = 50 , b = 15 它们的二进制格式如下所示:
a的二进制格式用A表示,A = 0011 0010;而b的二进制格式用B表示,B = 0000 1111。
那么A和B的位运算如下所示:
A&B = 0000 0010
A | B = 0011 1111
A ^ B = 0011 1101
~ A = 1100 1101
这里需要特别说明的是位补运算 ,注意下面的首位均为符号位,但是在做加减运算时需要忽略此符号位:
- 正数的位补运算 a = 50, ~a=? ,a的二进制数是 0011 0010 ,各位取反后得 1100 1101 首位1表示符号负数,故需要对其进行反补码运算,即是谁的补码运算后得到这个数 1100 1101 ; 1100 1101 反补码运算,先减1得 1100 1100 ,然后反码运算得 1011 0011 ,故得到最后的二进制数为 1011 0011 ,十进制数为 -51 。负数的整个位补运算,先各位取反,再减1,最后反码运算得出结果,即补码运算后的各位取反的反运算。
- 负数的位补运算 a = -51, ~a=? ,a的二进制数是 1011 0011 ,各位取反后得 0100 1100 ,然后加1得 0100 1101 ,最后做一次反码运算得 0011 0010 ,故得到的二进制数为 0011 0010 ,十进制数为 +50 。正数的整个位补运算,先各位取反,再加1,最后反码运算得出结果,即补码运算后的各位取反。
- 总结,位补运算的前后是互通的,都是负数补码运算后的各位取反操作的正反逻辑而已。
以Java代码来进行位运算的程序,如下所示。
public class Test { public static void main(String[] args) { int a = 50;// a的二进制格式 0011 0010 int b = 15;// b的二进制格式 0000 1111 int c = 0; c = a & b;// c的二进制格式 0000 0010,十进制格式 2 System.out.println(c);// 输出 2 c = a | b;// c的二进制格式 0011 1111,十进制格式 63 System.out.println(c);// 输出 63 c = a ^ b;// c的二进制格式 0011 1101,十进制格式 61 System.out.println(c);// 输出 61 c = ~a;// c的二进制格式 1011 0011,十进制格式 -51 System.out.println(c);// 输出 -51 c = a << 2;// a向左移2位,结果 1100 1000,十进制格式 200 System.out.println(c);// 输出 200 c = a >> 2;// a向右移2位,结果 1100,十进制格式 12 System.out.println(c);// 输出 12 c = a >>> 2;// a向右移2位,并移动得到的空位补零,结果 0000 1100,十进制格式 12 System.out.println(c);// 输出 12 } }
PS:左移动1位表示乘以2,左移动2位表示乘以2的平方。
逻辑运算符
操作符 | 描述 |
&& | 逻辑与运算符,当且仅当左右两边的操作数都为真时,条件才为真。 |
|| | 逻辑或运算符,只要左右两边的操作数任意一个为真,条件就为真。 |
! | 逻辑非运算符,用来反转操作数的逻辑状态。若操作数为true,则逻辑非运算后得到false。 |
实例演示:
public class MyFirst { public static void main(String[] args) { boolean a = true; boolean b = false; System.out.println(a&&b);// 逻辑与运算,因a和b中,有其中一个为false,故结果为false System.out.println(a||b);// 逻辑或运算,因a和b中,有其中一个为true,故结果为true System.out.println(!b);// 逻辑非运算,因b为false,故其相反就为true } }
赋值运算符
操作符 | 描述 |
= | 简单的赋值运算符,将右操作数赋值给左操作数。 |
+= | 加和赋值运算符,将左操作数和右操作数相加,并赋值给左操作数。 |
-= | 减和赋值运算符,左操作数减去右操作数,并赋值给左操作数。 |
*= | 乘和赋值运算符,将左操作数和右操作数相乘,并赋值给左操作数。 |
/= | 除和赋值运算符,左操作数除以右操作数,并赋值给左操作数。 |
(%)= | 取模和赋值运算符,左操作数取模右操作数,并赋值给左操作数。 |
<<= | 左移位和赋值运算符,左操作数向左移右操作数位,并赋值给左操作数。 |
>>= | 右移位和赋值运算符,左操作数向右移右操作数位,并赋值给左操作数。 |
&= | 按位与和赋值运算符,将左操作数和右操作数按位与运算,并赋值给左操作数。 |
^= | 按位异或和赋值运算符,将左操作数和右操作数按位异或运算,并赋值给左操作数。 |
|= | 按位或和赋值运算符,将左操作数和右操作数按位或运算,并赋值给左操作数。 |
实例演示:
public class MyFirst { public static void main(String[] args) { int a = 5; int b = 3; int c = 0; c = a;// 简单的赋值运算符,将a赋值给c。 System.out.println(c);// 输出 5 c += a;// 加和赋值运算符,将c和a相加,并赋值给c。 System.out.println(c);// 输出 10 c -= a;// 减和赋值运算符,c减去a,并赋值给c。 System.out.println(c);// 输出 5 c *= a;// 乘和赋值运算符,将c和a乘,并赋值给c。 System.out.println(c);// 输出 25 c /= a;// 除和赋值运算符,c除以a,并赋值给c。 System.out.println(c);// 输出 5 c %= b;// 取模和赋值运算符,将c取模b,并赋值给c。 System.out.println(c);// 输出 2 c <<= b;// 左移位和赋值运算符,将c的二进制数 0000 0010 左移b位数,并赋值给c。 System.out.println(c);// 二进制数为 0001 0000,输出 16 c >>= b;// 右移位和赋值运算符,将c的二进制数 0001 0000 右移b位数,并赋值给c。 System.out.println(c);// 二进制数为 0000 0010,输出 2 c &= b;// 按位与和赋值运算符,将c的二进制数0000 0010和b的二进制数0000 0011按位与,并赋值给c。 System.out.println(c);// 二进制数为 0000 0010,输出 2 c ^= b;// 按位异或和赋值运算符,将c的二进制数0000 0010和b的二进制数0000 0011按位异或,并赋值给c。 System.out.println(c);// 二进制数为0000 0001,输出 1 c |= b;// 按位或和赋值运算符,将c的二进制数0000 0001和b的二进制数0000 0011按位或,并赋值给c。 System.out.println(c);// 二进制数为 0000 0011,输出 3 } }
条件运算符
条件运算符(?:),也称为三元运算符。
语法形式:布尔表达式 ? 表达式1 :表达式2。
运算过程:如果布尔表达式的值为 true ,则返回 表达式1 的值,否则返回 表达式2 的值。
实例演示:
public class MyFirst { public static void main(String[] args) { int a = 5; int b = a==1?10:20;// 若a等于1为真,则返回10,即将10赋值给b;否则返回20。很明显此处的5和1是不相等的,故b被赋值为20 System.out.println(b);// 输出 20 } }
instanceof运算符
instanceof运算符,用于操作对象实例,判断该对象是否属于某个特定的类型(类类型或接口类型)。
语法形式:A instanceof B,A为对象实例,B为某一类类型,若A属于B类型,则返回true,否则返回false。
实例演示:
public class MyFirst { public static void main(String[] args) { Object a = 10;// 此处可以知道数字10的真正类型是Integer,由于Object是所有Java类型的父类,故可以以Object声明变量a System.out.println(a instanceof Boolean);// 输出 false System.out.println(a instanceof Integer);// 输出 true } }
Java运算符优先级
Java表达式可能存在多个运算符,运算符之间存在优先级的关系,级别高的运算符先执行运算,级别低的运算符后执行运算。在一个多运算符的表达式中,运算符优先级的不同会导致最后得出的结果大不相同。例如, a = 5 + 7 * 2 结果a是19,而不是24。Java中的加减乘除和括号等操作符的优先级,其实就跟数学中的一致,括号优先,再则乘除,然后加减,最后等于。
下表列出了Java运算符优先级排列,由高到低依次向下排列:
优先级 | 操作符 | 关联性 |
1 | ()、[]、. | 从左到右 |
2 | !、+(正)、-(负)、~、++、– | 从右到左 |
3 | *、/、% | 从左到右 |
4 | +(加)、-(减) | 从左到右 |
5 | <<、>>、>>> | 从左到右 |
6 | <、<=、>、>= | 从左到右 |
7 | ==、!= | 从左到右 |
8 | & | 从左到右 |
9 | ^ | 从左到右 |
10 | | | 从左到右 |
11 | && | 从左到右 |
12 | || | 从左到右 |
13 | ?: | 从右到左 |
14 | =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>= | 从右到左 |
2 Java变量
变量,就是用来操纵存储空间的数据的,Java变量是程序中最基本的存储单元,其要素包括了变量名、变量类型和作用域。Java变量可以分为局部变量、成员变量和静态变量。
Java是一种强类型语言,每个变量都必须声明其类型,即变量在使用前必须对其声明,有且只有在变量声明后才能为其分配相应长度的存储空间。
声明格式:type identifier [ = value][, identifier [= value] …] ;
其中type为Java数据类型。identifier是变量名。可以使用逗号隔开来声明多个同类型变量。
示例: String aa = “test and test”, bb = “test bb”;
注意:
- 每个变量都有其类型,类型可以是基本类型,也可以是引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。
局部变量
局部变量,是方法或语句块内部定义的变量,生命周期是从声明位置开始到方法或语句块结束为止。局部变量没有默认值,故局部变量必须先声明和初始化后才能被使用。
实例演示:
public class MyFirst { /** * 方法中的go变量只在方法中声明和初始化,然后被使用。 * 但是,它的作用域也就是在此方法中,若此方法运行结束了,则go变量的生命也到尽头了。 */ public void go() { String go = "走起,回家去!"; System.out.println(go); } public static void main(String[] args) { MyFirst myfirst = new MyFirst(); myfirst.go(); } }
成员变量
成员变量,也被称为实例变量,在方法外部、类的内部定义的变量。成员变量是从属于对象的,生命周期伴随对象的始终,从对象被声明创建到被回收为止。如果不自行初始化,他会自动初始化成该类型的默认初始值,如数值型变量的默认初始值为0或0.0,字符型变量的默认初始值为16位的0,布尔型变量的默认初始值为false。
public class MyFirst { int age = 11; /** * age是声明在类中、方法外的成员变量,故在方法中可以直接使用 */ public void myAge() { System.out.println("小米的年龄:" + age); } public static void main(String[] args) { MyFirst myfirst = new MyFirst(); myfirst.myAge(); } }
静态变量
静态变量,又称为类变量,以关键字 static 在类中、方法外声明的变量。静态变量是从属于类的,生命周期伴随类的始终,从类的加载到卸载为止。如果不自行初始化,他会自动初始化成该类型的默认初始值,如数值型变量的默认初始值为0或0.0,字符型变量的默认初始值为16位的0,布尔型变量的默认初始值为false。
注意:
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝,可以直接以 ClassName.VariableName 的方式访问,即 类名.静态变量名 。
- 静态变量除了被声明为常量外很少使用。常量是指声明为public/private,final和static类型的变量,常量初始化后不可再被改变。如 public final static String NAME = “test_name”;
public class MyFirst { public final static String NAME = "test_name"; /** * 常量NAME不管哪里都可以直接调用 */ public void myName() { System.out.println("小米的名称:" + MyFirst.NAME); } public static void main(String[] args) { MyFirst myfirst = new MyFirst(); myfirst.myName(); System.out.println("小明的名称:" + MyFirst.NAME); } }
变量命名规范
我们对于变量的命名一般有如下几种,方便我们见其名而知其意。但是需要注意的是,命名规范并不代表规定。
- 成员变量:首字母小写和驼峰原则,如 myName 。
- 局部变量:与成员变量一样,首字母小写和驼峰原则。
- 常量:大写字母和下划线,如 MAX_VALUE 。
- 类名:首字母大写和驼峰原则,如 MyFirst 。
- 方法名:首字母小写和驼峰原则,如 goHome() 。