概要
这一章的复习主要涵常见的 运算符 及经常用到的 运算符操作 和 关键字。这里整理的都是个人觉得比较重要重新认真分析的东西,不一定全部为基础,如果有不准确的地方,还望大佬从评论区指出,感激不尽。
文章中的所有的自定义的测试都在自己的 java-review
仓库中,本文对应的链接:
操作符
算数运算符
在运算过程中会自动进行类型提升
1 | int i = 1; |
算数运算符中重要的就是 +
操作符,以为它支持对 String
的操作用来连接字符串,式子中存在 String
类型的时候,最终类型会被转换为 String
类型,转换时机还是跟运算顺序有关,由结合律决定,详细的 String
会在后面的 String
中细致分析。
等价操作符
==
和 !=
等价性操作符对于基本数据类型和对象分开操作
- 基本类型 直接比较数值,例如:
int
、double
等 - 对象引用 比较引用是否相等,是否指向同一个对象
在 java
的基类 java.lang.Object
的 boolean equals(Object obj)
方法,就是使用了 ==
操作符来进行比较是否等价
因此所有的 java
类型调用 equals(obj)
方法的时候,其实就调用了 ==
来比较对象的,需要重写 equals(obj)
方法才能按照指定的方式来比较!,String
、Integer
等
1 | A a1 = new A(12); |
String
中重写了基类中的 equals(obj)
方法:
- 如果是同一个对象,直接返回
true
- 判断是否为
String
类型对象 - 判断编码格式是否相同
- 根据编码类型调用对应的比较方法
1 | // java 12 source |
直接常量
指定进制
format | 进制 |
---|---|
0b10 | 二进制 |
100 | 十进制(默认) |
0144 | 八进制 |
0x64 | 十六进制 |
指定类型
format | suffix | type |
---|---|---|
1.2F | f / F | float |
123L | l / L | long |
在前面有提到整数默认类型为 int
,非整数类型默认类型为 double
指数计数
e/E
用来表示 10 的幂次,默认为 double
类型
1 | double d = 1.2e3; |
移位操作符
这部分应该是除了算数运算和比较运算符之外最多的了。
>>
操作为 算数左/右移,左边的补位跟符号有关- 正数补
0
- 负数补
1
- 正数补
>>>
为逻辑右移,就当做直接右移就完事了。
通常使用的时候使用 >>>
逻辑右移,避免在处理负数上出现状况
1 | int mid = lo + ((hi - lo) >>> 1); |
自动递增和递减
前置递增没有什么特点,主要举例分析后置自动递增操作符的机制。
后置递增机制 (递减同理):
- 将 局部变量表中的值 压入 操作数栈 中
- 局部变量表的值
+ 1
- 将结果从 操作数栈 中弹出,并赋值给 局部变量表
1 | // java test |
之所以结果出现 i = 0
,就是因为后置递增的机制的原因,i
在完成赋值之后又被重复赋值上了保存到 temp
中的原来的值。
将上述机制可以等效为:
因为 java
中不能使用指针,无法完成基本类型传地址对原变量进行修改的操作,所以这里使用 c++
来完成对上述机制的描述。
1 | // c++ test |
位运算操作符
&
按位与的操作
取最后一个
1
表示的值去掉二进制表示中的最后一个
1
1 | // java test |
~
按位取反运算符
-x = ~x + 1
的证明
1 | // java test |
^
按位异或操作
^
的性质就是相同的数进行异或为 0
,这个性质就适用于
- 一个数组除了 一个数出现奇数次 外,其他的数都出现了 偶数次,求这个数
操作符优先级
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ( ) [ ] |
–> |
2 | ! + - ~ ++ -- |
<– |
3 | * / % |
–> |
4 | + - |
–> |
5 | << >> >>> |
–> |
6 | < <= > >= instanceof |
–> |
7 | == != |
–> |
8 | & |
–> |
9 | ^ |
–> |
10 | | |
–> |
11 | && |
–> |
12 | || |
–> |
13 | ? : |
<– |
14 | = += -= *= /= &= |= ^= ~= <<= >>= >>>= |
<– |
关键字
package 关键字
必须是第一条代码
import 关键字
编译器遇到 import
关键字会从 classpath
中开始查找对应路径的 .class
文件。
this 关键字
this
当前对象引用
this
关键字只 能用于方法中,this
代表的是调用当前方法的对象实例方法返回 当前引用本身,参考
StringBuilder
中的StringBuilder append(String )
1
2
3
4
5
6
7
8// java test
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("A").append("B").append("C").append("D");
System.out.println("str: " + stringBuilder);
///:~ str: ABCDStringBuilder
源码分析1
2
3
4
5
6
7
8
9
10
11
12
13
14// java 12 source
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence {
public StringBuilder append(String str) {
super.append(str);
return this; // 返回当前对象引用
}
}this
可以用于区分同名的 形参 和 类的成员变量if result 加 成员变量 不加 形参 不使用
this
关键字修饰,默认情况下调用的为 形参1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43// java test
public class This {
private int value;
private This() {}
/*
this 在构造器中调用构造器
1. 必须在第一句
2. 能且只能调用一次
*/
private This(int value) {
this();
this.value = value;
}
private void paramWithoutThis(int value) {
System.out.println("without: " + value);
}
private void paramUseThis(int value) {
System.out.println("useThis: " + this.value);
}
private static void thisObjRef() {
This _this = new This(1);
System.out.println("_this.value: " + _this.value);
_this.paramUseThis(2);
_this.paramWithoutThis(2);
/* Output:
_this.value: 1
useThis: 1
without: 2
*///:~
}
}this()
在构造器中调用构造器只能在 构造器中 ,必须 在第一句,能且 只能 调用一次
ClassName.this
来引用外部类适用于 外部类的成员变量或者方法 和 内部类 重名的时候
ClassName.this
用于锁定外部类对象,进而可以调用外部类的成员变量和方法test()
和this.test()
都会调用当前对象的方法,即内部类对象,所以都是调用了内部类的成员变量和方法
1 | // java test |
static 关键字
- 使用了
static
修饰的变量或者方法会独立出来,不会与包含它的类的任何实例对象关联再一起。 static
修饰的 方法 和 属性,可以通过全类名.变量名/方法名
直接调用
静态和非静态的关系
- 静态方法中不能直接调用非静态的属性属性/方法,只能通过对象实例的引用 来调用 拥有权限的属性/方法
- 非静态的方法中可以直接调用静态的方法
关于 static
和 内部类 的关系会放到后面来分析。
例如下面的测试中,value
属性独立了出来,不和任何一个实例对象相关联,所有的 Static
公用这个属性
1 | // java test |
final 关键字
final 数据
- 适用情况
- 永远不发生改变的常量
- 运行时被初始化的值,而不希望被改变
final
修饰的变量同样可以先声明,再初始化- 成员变量必须在
static
和final
共同修改的域占据一段 不可修改 的存储空间final
同样可以用来修饰 形参,这个类似于c++
中的const
关键字,都是锁定常量为 只读,无法进行修改不管是 基本类型 还是 包装类型,使用了
final
关键字修饰以后都 不能进行修改操作
1 | // java test |
final 方法
防止方法覆盖(重写)final
关键字将方法锁定,其导出类中无法对该方法进行重写操作private
关键字修饰方法都是隐式地指定为了 final
,无法被重写,给 private
修改的方法添加 final
关键字的是多余的
final 类
禁止继承,不会有任何子类,其内部属性都别隐式地指定为了 final
变量