点击进入我的博客
3.1更简单的打印语句
System.out.println("imbug");
通过编写一个小类库,并通过import static该方法来实现简化打印(基本没啥用)。
public class Print {
public static void println(String str) {
System.out.println(str);
}
}
import static s1.Print.println;
public class Test {
public static void main(String[] args) {
println("imbug");
}
}
3.2 使用Java操作符
- 操作符接受一个或多个参数,并生成一个新值
- 有些操作符可能会改变操作数本身的值
- 几乎所有的操作符都只能操作基本类型;
=、==、!=能操作所有的对象;String类支持+、+=操作符
3.3 优先级
运算符优先级表.png
- 操作符是有优先级的。
- 个人认为:死记硬背操作符的优先级除了应付大学考试和智障笔试题之外,并无卵用~只要理解了运算符的原理再来看优先级有易如反掌了~
- 如果有人写这样的代码请打死他:
System.out.println(a<<=b+=c>>=5); -
System.out.println()中的+运算符可能会表示字符串拼接,还有可能进行字符串转换。
3.4 赋值
赋值=的意思是取右边的值把它复制给左边。
左边的值必须是明确的、已命名的变量。
右值可以是任何常熟、变量或者表达式(只要它能生成一个值)。
基本类型传递的是值,对象类型传递的是引用。
3.5 算术操作符
+、-、*、/、%
/:整数的除法会直接干掉小数位而不是四舍五入
+、-:还可以用作正负号
3.6 自动递增和递减
++、--
前缀式:++a先执行运算再生成值,即++a == a is true
后缀式:a++先生成值再执行运算,即a == a++ is true
3.7 关系运算符
>、<、>=、<=、!=、==
- 关系操作符生成的是一个
boolean的结果。 -
大于、小于、大于等于、小于等于不适用于
boolean类型 - 等于和不等于适应于全部基本数据类型及对象类型
- 等于和不等于作用于对象类型时比较的是引用(我更倾向于用C++中的地址来理解这个概念)
- 对基本数据类型的包装类、
String、BigInteger、BigDecimal的equals方法比较的是值 - 如果你自己的
class没有重写equals方法,那么equals方法使用的是Object的equals方法,即比较引用。
数值的包装类
Integer x1 = new Integer(10);
Integer x2 = new Integer(10);
System.out.println("x1 == x2: " + (x1 == x2));
System.out.println("x1.equals(x2): " + x1.equals(x2));
// x1 == x2: false
// x1.equals(x2): true
Integer y1 = 10;
Integer y2 = 10;
System.out.println("y1 == y2: " + (y1 == y2));
System.out.println("y1.equals(y2): " + y1.equals(y2));
// y1 == y2: true
// y1.equals(y2): true
Integer z1 = 1000;
Integer z2 = 1000;
System.out.println("z1 == z2: " + (z1 == z2));
System.out.println("z1.equals(z2): " + z1.equals(z2));
//z1 == z2: false
//z1.equals(z2): true
上述代码的.class文件反编译后的代码
Integer x1 = new Integer(10);
Integer x2 = new Integer(10);
System.out.println((new StringBuilder()).append("x1 == x2: ").append(x1 == x2).toString());
System.out.println((new StringBuilder()).append("x1.equals(x2): ").append(x1.equals(x2)).toString());
Integer y1 = Integer.valueOf(10);
Integer y2 = Integer.valueOf(10);
System.out.println((new StringBuilder()).append("y1 == y2: ").append(y1 == y2).toString());
System.out.println((new StringBuilder()).append("y1.equals(y2): ").append(y1.equals(y2)).toString());
Integer z1 = Integer.valueOf(1000);
Integer z2 = Integer.valueOf(1000);
System.out.println((new StringBuilder()).append("z1 == z2: ").append(z1 == z2).toString());
System.out.println((new StringBuilder()).append("z1.equals(z2): ").append(z1.equals(z2)).toString());
通过new Integer新建对象
-
new Integer每次都会新建对象,所以==的结果为false
自动装箱与拆箱
- 自动装箱:用赋值运算符
=把一个数值或基本类型变量赋值给一个包装类变量(Integer y1 = 10)。装箱调用的是Integer.valueOf(10)方法。 - 自动拆箱:用赋值运算符
=把一个包装类赋值给一个基本类型变量(int y3 = y1),或者是在包装类进行数值运算时。拆箱调用的是Integer#intValue()方法。 -
装箱方法的坑(笔面试题):下面是
Integer.valueOf(int i)的源代码。可以看出当装箱的数值在-128到127之间是,返回的对象是IntegerCache中提前new出来的对象,所以y1 == y2的结果是true;当装箱的数值超出该范围,则返回的是new出来的对象,所以z1 == z2的结果为false。 - 其他的装箱方法:
Byte、Short、Integer、Long的范围都是[-128,127];Character的范围是[0,127];Float、Double全部是new出来的新对象;Boolean都是预定义好的true和false。有趣的是,这些代码作者是一样的,但写法各不相同。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
备注内容:可以从https://varaneckas.com/jad/下载Java反编译工具JAD;或者可用从http://jd.benow.ca/下载反编译工具JD-GUI
3.8 逻辑操作符
&&、||、!
- 逻辑运算符只能根据两个布尔值参数的逻辑关系,生成一个布尔值。
布尔值短路
- 即一旦能够明确无误地确定整个表达式的值,就不再计算表达式剩余的部分了
-
&&:遇到第一个false则不执行后边的代码 -
||:遇到第一个true则不执行后边的代码
public static boolean func1() {
System.out.println("func1");
return true;
}
public static boolean func2() {
System.out.println("func2");
return false;
}
public static boolean func3() {
System.out.println("func3");
return true;
}
if(func1() && func2() && func3()); // 不执行func3中的内容
if(func1() || func2() || func3()); // 不执行func2和fanc3中的内容
- 面试题:如何不使用条件语句控制流程。
// 不使用if来控制该流程
if(func1()) {
func2();
}
// 方法
boolean var = func1() && func2();
3.9 直接常量
- 前缀
0x、0X:表示16进制数字 - 前缀
0:表示8进制数字 - 后缀
l、L:表示long类型。在写代码的时候,由于小写的l容易和数字1混淆,所以各种规范中都不建议(禁止)使用小写的l表示长整数。最简单就全部用大写就好了! - 后缀
f、F:表示float类型。 - 后缀
d、D:表示double类型。 -
e、E:指数计数,表示10的幂
3.10 按位操作符
&、|、^、~
&=、|=、^=
-
boolean:可以把boolean值看成单比特值对待,&、|、^的操作相同,但是~不能用于布尔值。
3.11 移位操作符
<<:高位(包括符号位)舍弃,低位补零。
>>:有符号右移运算,若高位是1,则高位补1;若高位是0,则高位补0。
>>>:无符号右移,最高位补0。
- 移位操作符只能用来处理整数类型。
-
char、byte、short进行移位操作时,会先被转成int类型,并且结果也是int类型 -
long类型移位还是long
<<=、>>=、>>>=
- 注意:在对
byte、short进行>>>=无符号右移等于运算时,整个流程是先向上转化成int——进行移位运算——向下转化(强制截取)成byte或short,所以会导致移位后对结果不正确。
short s = -1;
System.out.println(Integer.toBinaryString(s));
// 11111111111111111111111111111111
System.out.println(Integer.toBinaryString(s >>> 10));
// 1111111111111111111111
s >>>= 10;
System.out.println(Integer.toBinaryString(s));
// 11111111111111111111111111111111
3.12 三目运算符
boolean-exp ? val1 : val2
3.13 字符串运算符
+、+=
3.14 操作符常犯错误
- Java中
if、while语句必须使用boolean值,所以不会出现==被写成=的问题;除非是两个boolean值 - Java编译器也能够防止逻辑与或(
&&、||)和按位与或(&、|)的问题,除非是两个boolean值
3.15 类型转换操作符
- 既可以对数值进行转换,也可以对数值变量进行转化
- 向下转化必须要强制转化,否则编译失败(移位等于、算数等于时不会)
- 向上转化不必显示进行转化
- 除布尔值之外,其他类型都可以互相转化
- 浮点数转成整数值的时候直接截尾,不会进行四舍五入
- 表达式的最大数据类型决定了表达式的数据类型
3.16 没有sizeof
Java所有基本数据类型的size是确定的,所以不需要sizeof
3.17 操作符小结
-
char、byte、short在使用算术操作符和移位操作符的时候都会被转成int,必须显示类型转换回原来的类型。以下注释掉的都是编译错误的。
short s1 = 10;
short s2 = 10;
// short s3 = s1 + s2;
// short s4 = s1 >> 1;
-
char、byte、short在进行复合赋值运算(移位等于、算数等于)时不需要强制转化。 -
int类型要小心结果溢出 - 除
boolean外,任何基本类型都可以通过类型转换变成其他基本类型 - 必须留意向下转化的的结果,因为可能存在丢失信息的可能性









网友评论