1 运算符
1.0 运算符的优先级
转自@zll0927CSDN博客的总结:括单算关位逻条赋。
运算符类别(级别) | 运算符 |
---|---|
括号(1级) | “()”、"[ ]"(数组取下标) 、"."(取成员变量) |
单目(2级)(从右向左运算) | “!”、"+"(正)、"-"(负)、"~"(按位取反)、"++"、"–" |
算术(3-5级) | “*”、"/"、"%" ---->>>> “+” 、"-" ---->>>> “<<”、">>"、">>>" |
关系(6-7级) | “<”、"<="、">"、">="、“instanceof” ---->>>> “==”、"!=" |
位(8-10级)(特殊的单目) | “&” ---->>>> “^” ---->>>> “|” |
逻辑(11-12级) | “&&” ---->>>> “| |” |
条件[三目运算符] (13级) | “? :” |
赋值(14级)(从右向左赋值) | “=”、"+="、"-+"、"*="、"/="、"%="、"&="、"|="、"^="、"~="、"<<="、">>="、">>>=" |
- 单目、双目、三目运算符分别表示可以操作1、2、3个变量。
- “---->>>>” 用于区别同一类里面的优先等级,每遇到一个 “---->>>>” 优先级降一级,如:单目类里%优先级高于+。
- 有几个特殊之处需要注意:
- “.”与“()”同级
- “&”、“^”、“|”优先级位于算术、关系之后
- 赋值与普通的单目的结合方向从右向左
- “+”、“|”、“&”有与运算符重载的意义。当“+”两端为String类型时,作用为拼串;其余时候均为算术加法。“|”、“&”两端为boolean类型时,作用为与、或判断;两端为整数类型时,作用为与、或算法。
- 所有运算符操作的最小类型为int,byte/short在运算前必须将算式强转为byte/short。byte/short直接与数字(默认的int/double)运算时会报错损失精度。(这也是byte/short不用做存放年龄的原因)
- 在一个循环中,"++“多用于计算次数,”+="多用于计算总和。
1.1 "+"、"-"、"*"、"/"、"%"
-
执行"+"、"-"、"*"、"/"、"%"操作时,如果运算的变量中有浮点数,那么整数类型都会升级转换成浮点数参与运算,结果是浮点数。
-
因为浮点数的运算会出现精度问题,应尽量避免使用浮点数参与运算,整数类型的运算避免出现小数点,浮点类型的计算使用BigDecimal类,如变量x增长原来的10%,不应直接乘以1.1,应该先乘以11再除以10。另外浮点数不能使用">>"、"<<"、">>>"、"&"、"|"、"^"、"~"。
-
因为char类型可以转换为ascii码,可以以整数数值的形式进行赋值,所以其可以使用的运算符与整数类型一致。
-
“+”、"*"运算时变量可以调换顺序,如果运算时变量的数据类型不一致,表示范围大的数据类型需要前置,后面的小范围数据会自动转换为大范围的数据类型(如“365L * 24 * 60 * 60 * 1000”算一年有多少毫秒)。而"%"、"/"、"-"必须注意运算顺序。
-
"+"加法的运算符重载。
数字类型、char类型在执行加法时都是做算术相加(char在相加时是使用其ascii码);若算式其中一目为String时,加法的作用是拼串,所以如果想将其他基本数据类型转换为String,只需要加一个空双引号。
public class Test1{
public static void main(String[] args){
System.out.println(1 + 1);//算数加法
System.out.println(1 + "1");//追加连接
System.out.println(1 + 1 + "1");//21
System.out.println(1 + "1" + 1);//"11" + 1 = 111
System.out.println(1 + '1' + "1");
//int + char
//1 + 49 + "1"= 50 + "1" = 501
System.out.println(1 + '1' + "1");
//double + char
//1.0 + 49 + "1"= 50.0 + "1" = 50.01
System.out.println(1 + "1" + '1');//"11" + '1' = 111
System.out.println(11 + "");//此时输出的11是一个字符串"11"
System.out.println("" + 1 + 2 + 3);//输出123而不是6
}
}
在System.out打印输出时,单引号中的char类型可能会变成ascii码参与运算,char要想原文本显示必须使用双引号或者升级为String。
- “-”、"/"、"%"运算时还需注意
public class Test2{
public static void main(String[] args){
System.out.println(5 / 2);//2 整数/整数 = 整数
System.out.println(5 / 2.0);// ->5.0 / 2.0 = 2.5 即整数/小数 = 小数
System.out.println(5 - 0.0);//Infinity -> 无穷大
System.out.println(5 / 0.0);//Infinity -> 无穷大
System.out.println(0.0 / 0.0);//NaN = not a number = 不是一个数
}
}
- 扩展:Math.random()的使用
注意random()的取值范围是[0,1),所以如果要取[0,10]的整数随机数,需要乘以11。如果需要取所有的三位数,需要乘以900再加100。总之记住random()范围为[0,0.999…)在这个基础上做加法和乘法得到结果即可。
1.2 "+="、"-+"、"*="、"/="、"%="、"&="、"|="、"^="、"~="、"<<="、">>="、">>>="
以"+="为例,x += n <----> x = x + n。能够保证运算符的左边的数据类型不发生改变,即隐式的强转。
public class Test3{
public static void main(String[] args){
int num = 45;
//在num的基础上 + 5.5然后再赋值给num
num += 5.5;//等价num = (int)(num + 5.5);45.0 + 5.5 = 50.5 -> int
System.out.println(num);//--->50
}
}
public class Test4{
public static void main(String[] args){
short x = 1;
x = x + 1;//short = int
System.out.println(x);//会导致精度损失
short y = 1;
y += 1;//等价 y = (short)(y + 1);
System.out.println(y);//2
}
}
- 做减法、除法、模运算时,只有x = x - n这样的可以简写为 x -= n。x = n - x不能这样简写。
1.3 "++"、"--"
自增自减运算符,多用于循环中。以“++”为例,JVM处理"x++“和”++x"的方法分别为“先取值,再运算”和“先运算,再取值”。取值时即完成本行语句(显示/运算中的赋值),下面的这个变量均使用运算后的值,取值消亡。
public class Test5{
public static void main(String[] args){
int x = 45;
System.out.println(x++);//x++ -> 45,先取值为45,完成显示
System.out.println(x); //x -> 46,使用运算后的值,取值消亡
}
}
public class Test6{
public static void main(String[] args){
int x = 45;
System.out.println(++x);//++x -> 46,先运算,后取值46
System.out.println(x); //x -> 46,使用++x运算后的值,取值消亡
}
}
public class Test7{
public static void main(String[] args){
int x = 45;
int y = x++ + 2;//x++先取值为45,完成运算中赋值
System.out.println(x);//x -> 46,使用x++运算后的值,取值消亡
System.out.println(y);//y -> 47,使用++x运算后的值,取值消亡
}
}
public class Test8{
public static void main(String[] args){
int x = 10;
int y = 20;
int z = x++ + ++y;//z = 10 + 21,x++先取值为10,++x先取值为21,完成运算中赋值
System.out.println(x);//x -> 11,使用x++运算后的值,取值消亡
System.out.println(y);//y -> 21,使用++x运算后的值,取值消亡
System.out.println(z);//z -> 31
}
}
public class Test9{
public static void main(String[] args){
int x = 45;
x = x ++;//x++先取值为45,完成对自身x的赋值
System.out.println(x);//x -> 45,"++"优先级高于"=",所以x最后获取的值为x++的取值
}
}
1.4 ">"、"<"、">="、"<="、"! "、"="、"!="、"=="
常用于逻辑判断流程,其中:
“>”、"<"、">="、"<="返回类型都是boolean类型。遇到“boolean isOK = x < 10时”由于优先级问题会先执行x<10。
“!”:意义为 “非”,后面接boolean类型的值(!true = false,!false = true)。
“!=”:判断左右两边的值是否不相等[例:System.out.println(45 != 55);–>true]。
- “=“和”= =“之间的区别?
“=”:赋值运算符,将右侧的值交给左侧的变量保管;”= =”:判断左右两边的值是否相等,返回boolean类型值。 - 注意以下例子,在if判断中要写"==","="在这里是赋值的意思
public class Test10{
public static void main(String[] args){
boolean isOk = false;
//=:赋值运算符
if(isOk = true){
System.out.println("true");//一直打印“true”
}else{
System.out.println("false");
}
}
}
1.5 "&&"、"||"、"&"、"|"
-
面试题:
1 "&&“和”&"之间的区别?-
相同点:"&&“和”&"都是逻辑的与,相当于“并且”的意思,需要前后两个条件都成立。
-
不同点:"&&“叫做逻辑的短路与,有短路特性,即**如果通过前面的条件可以得出最终结果的话,后面条件直接舍弃,不再判断。**前者为true,后者需判断;当前者为false,后者不需判断。但是”&"不具有短路特性,即如果前者为false,后者还是需要判断一下,效率较低,较少使用。
2 "||“和”|"之间的区别?
-
相同点:"||“和”|"都是逻辑的或,相当于“或者”的意思,需要前后其中一个条件成立就可以。
-
不同点:"||“叫做逻辑短路或,有短路特性。前者为false,后者需判断;当前者为true,后者不需判断。但是”|"不具有短路特性,即如果前者为false,后者还是需要判断一下,效率较低,较少使用。
-
1.6 "&"、"|"、"^"、"~"
基本用法(非重点)
- “&”:按位的与,要求上下都是1时才写1。当后面接"==“时由于”= =“优先级高于”&",此时需要对&的变量两端加括号。
System.out.println(9 & 5);//-->1
9:8+1=00000...0001001
5:4+1=00000...0000101 &
--------------------
00000...0000001 : 1
- 重点(提高效率)★:
"&“的特性:在某些情况下可以取代”%",当我们拿着一个正数"%"上2n的时候,结果等价于我们拿着这个正数&上2n-1的结果。
27 %2 %4 %8 %16.....%2(n)
1 3 3 11
27 &1 &3 &7 &15.....&2(n)-1
1 3 3 11
以“27 & 7”为例
27:16 + 8 + 2 + 1 = 000000...00011011
7: 000000...00000111 &
--------------------
000000...00000011 : 3
x % 2^n <--> x & (2^n)-1
x % 8 <--> x & 7
x % 4 <--> x & 3
- “|”:按位的或,要求上下只要有1就写1。
System.out.println(9 | 5);//-->13
9:8+1=00000...0001001
5:4+1=00000...0000101 |
-------------------
00000...0001101 : 8+4+1=13
- “^”:按位的异或,要求上下不一样的时候才写1。
System.out.println(9 ^ 5);//12
9:8+1=00000...0001001
5:4+1=00000...0000101 ^
-------------------
00000...0001100 : 8+4=12
- 重点(提高效率)★:
"^"的特性:可以不借助第三块空间的方式交换两个变量的值
int x = 45;
int y = 90;
x = x ^ y;
y = x ^ y;
x = x ^ y;
int z = x;
x = y;
y = z;
public class Test11{
public static void main(String[] agtbhs){
int x = 56;
int y = 88;
x = x ^ y;
y = x ^ y;
x = x ^ y;
/**
int x = 56;
int y = 88;
56:32 + 16 + 8 = 00000...000111000
88:64 + 16 + 8 = 00000...001011000
x = x ^ y;
00000...000111000
00000...001011000 ^
--------------------
00000...001100000 : 32 + 64 = 96 = x
y = x ^ y;
00000...001100000
00000...001011000 ^
-------------------
00000...000111000 : 32 + 16 + 8 = 56 = y
x = x ^ y;
00000...001100000
00000...000111000 ^
-------------------
00000...001011000 : 64 + 16 + 8 = 88 = x
*/
System.out.println(x + "\n" + y);
}
}
- “~”:按位的取反,0–>1 1–>0
System.out.println(~9);//-10
9:8+1=00000...0001001
得到
~9 11111...1110110 (负数的计算)= -1-1-8 = -10
1.7 ">>"、"<<"、">>>"(提高效率)
"<<“相当于乘,”>>"相当于除以,移动n位相当于乘/除以2n
*2 *4 *8 *16....*2^n
<<1 <<2 <<3 <<4....<<n
/2 /4 /8 /16..../2^n
>>1 >>2 >>3 >>4....>>n
-
面试题:
1 在计算机里面 如何高效的求出2的3次方数?
2 << 1 << 1 -> 2 << 22 在计算机里面 如何高效的求出2的31次方数-1的结果?
(2 << 30) - 13 >>和>>>之间的区别?
“>>”:有符号右移,移动之后空缺的高位看原本的符号位。首位是0补0,是1补1。
01010010 >> 2
移位后:00010100
11101011 >> 3
移位后:11111101
“>>>”:叫做无符号右移 移动之后空缺的高位直接补0。
01010010 >>> 2
移位后:00010100
11101011 >>> 3
移位后:00011101
- 例:
int x = 9;
x >> 1;// <-->x / 2 = 4
9:00000...0001001
移位后:00000...000100
int x = 9;
x << 2;//<-->x * 4
9:0000..0001001
移位后:0000..000100100
int x = 5;
x << 1;//<-->x * 2 = 10
5:0000.0000101
移位后:0000.00001010
1.8 " ? : "
格式:“boolean类型 ? true对应的值 : false对应的值”,可以用来取代简单的if-else语句。true/false对应的值处只能赋给变量的值而不能填语句。
三目运算符的第一部分必须是boolean类型的判断句。如果第一部分结果位true 那么执行第二部分;如果第一部分结果位false 那么执行第三部分。
如果在if、while类似的判断中遇到 boolean?true:false,可以简化成boolean,boolean?false:true可以简化成 !boolean。
2 变量
-
面试题:
-
Java中的变量分为哪种?
成员变量(也称实例变量、属性):定义在类体里面的变量。
局部变量(自动变量):定义在方法体里面的变量。
注意:java中没有全局变量的概念 -
成员变量和局部变量之间的区别?
1 定义的位置不同
成员变量:定义在类体里面。
局部变量:定义在方法体里面。(流程控制语句也存在于方法体内,其中的变量也属于局部变量)2 作用范围(作用域)不同
成员变量:也叫属性,表示对象有什么,依赖于对象存在,只要所依赖的对象没有消亡都可以访问。
局部变量:从定义的那一行开始,一直到所在的方法体结束之前可以访问,所在的方法体一旦执行结束,局部变量立即消亡,依赖于方法存在。3:默认值不同
成员变量:即使不赋值也有默认值。
局部变量:没有默认值,要求在使用之前必须先赋值。
-
-
注意:
- 成员变量和局部变量可以重名,在成员变量和局部变量重名的时候 如果直接访问该变量默认是局部变量(就近原则)。
- 当我们想要访问成员变量的时候,需要在这个变量的前面加上"this."。
- 变量定义的位置:“数据类型 变量名”出现的位置,其中这里的变量名可以有多个;类体里定义了后默认赋值,局部变量使用前必须赋值。
3 jar包的使用
如何使用jar指令制作jar包已经在前面的文档里叙述了,jar包的使用记录一下:
方法一:解压jar包,将.class文件放在classpath指定的目录(默认为当前.java源文件所在的目录)中,在源文件直接调用这个类
方法二:
1.在cmd中一次性设置一个classpath
指令为:
set CLASSPATH=.;....jar //依次为一个点(为了后面java指令运行时寻找当前文件下的.class文件)、一个分号(作为分割两个不同路径的符号)、一个.jar路径(javac时要加载.jar文件中存放的要引用的.class文件)
javac xxx.java
java xxx
- 拓展:
1 在一个静态方法中被调用的方法必须也要声明为静态的,调用静态方法时直接用类名调用。
2 当一个需求多次出现,需要将其封装为一个方法。