Ⅲ 操作符
---4.6更新---
3.4 赋值
-
基本类型的赋值就是简单的值传递,因为基本类型中存储的是值。
-
对象“赋值”是真正操作的其实是对象的引用。假如我们要将“A对象赋值给B对象”,事实上是将B对象的引用指向了A对象的内存空间。此时,无论修改A对象还是B对象引用的值(实际上是同一块内存空间),A与B都会受到影响。
-
上述问题被称为“别名现象”。
//举个例子,假如Person类有一个属性是int型的age。
class Person{
int age;
}
public static void main(String[] args){
Person tom=new Person();
Person jerry=new Person();
//基本类型赋值
tom.age=10;
jerry.age=20;
//对象赋值,此时tom和jerry的age都变为20
tom=jerry
//此时tom和jerry的age都是15
tom.age=15
}
- 上述这段代码就是“别名现象”,那么如何避免呢?
如果将tom=jerry
改为tom.age=jerry.age
那么,就将对象的引用赋值转化为基本类型的值赋值,就避免了这一问题。
3.6 自动递增和递减
- 自增和自减是最著名的快捷运算了。相应地又分为“前缀”和“后缀”。对于“++a”,会先执行运算,再生成值;对于“a++”,会先生成值,再执行运算。用一段代码就可以很清晰的理解了。
public static void main(String[] args){
int a=1;
++a;//a=2
a++;//a=2
++a;//a=4
}
同理,自减也是如此。
-
大家都知道C++之所以叫C++,可以通过自增操作符来解释。暗示着“超越C一步”。
-
有趣的是,在早期一次有关于Java的演讲中,Bill Joy宣称“Java=C++--”,这意味着Java去除了C++一些困难繁琐和没有必要的东西,成为一种更精简的语言。
3.7 关系操作符
-
在基本类型的变量之间,可以使用“==”或者“!=”来判断两个变量值是否相同;但是在对象之间,“==”与“!=”是用来判断两个对象的引用是否指向同一块内存空间,若要比较两个对象引用类型是否等价,可以使用
Object
类的equals()
方法。 -
但是,仅仅上述一句对
equals()
的理解是不全面的。对于类库包装类,可以使用equals()
来比较两个对象引用的值是否相等。对于自定义类的对象,equals()
默认的行为还是比较引用,若想让它去比较引用的值,需要在类中重写equals()
方法。说的很拗口,但是这确实是一个隐藏的“灾难”。 -
可以通过以下两段代码来辅助理解。
//包装类
Integer n1=new Integer(10)
Integer n2=new Integer(10)
n1.equals(n2)//true
//自定义类
Person p1=new Person()
Person p2=new Person()
p1.age=10
p2.age=10
p1.equals(p2)//false
不过大多数的Java类库都实现了equals()
来使他们去比较值。只是在我们的使用中,假如出现了问题,要知道,原始的equals()
默认行为还是比较引用,只不过常常被重写了。
- 去看一看源码:
Object.java
:
Integer.java
:
3.8 逻辑操作符
-
在进行逻辑操作时,有一种有趣的现象,叫做“短路”,即当能够准确无误地确定整个表达式地值时,就不需要再计算余下部分了。
-
举个例子:比如运算
true&false&true
,当计算到true&false
返回false时,后面将不再计算,因为无论后面是真是假,总地结果都是false,这是一种潜在地性能提升。
3.10 按位操作符
-
按位操作符源于C语言面向底层的操作,这种操作是用来直接操作硬件寄存器内的二进制位。Java的设计初衷是嵌入电视机机顶盒内,所以这些面向底层的操作被保留了下来,但是现在已经很少用到。
-
主要规范:
1,1 | 1,0 | 0,0 | |
---|---|---|---|
按位与(&) | 1 | 0 | 0 |
按位或 (l) | 1 | 1 | 0 |
异或(^) | 0 | 1 | 0 |
3.15 类型转换操作符
-
类型转换(cast)的愿意是“模型铸造”。在适当的时候,Java会将一种数据类型自动转化为另一种。
-
在C和C++中,类型转换不如在Java中那么安全。但是,当面临“窄化操作”时,有可能面临信息丢失的危险,此时编译器会强制我们进行显式的类型转换。
-
对于基本类型,除了布尔型,其他类型之间可以进行转换。但是对于“类”的对象来说,若要进行类之间的转换,必须采取特殊的方法。(此书后面会详细讲对象之间转换的方式)
-
在进行“窄化操作”时,有两种方式:截尾和舍入。
解尾其实大家都熟悉,在将float
或者double
类型转化为int
时,会将精度丢失,比如,2.3与2.89转化为int
时,都会变为2。
舍入就是进行通俗的四舍五入,这需要用到java.lang.round()
方法,前面提到java.lang
是默认引入到每个java文件的,所以不需要额外的import
。 -
在对不同的基本类型进行算术运算或者是按位运算时,表达式中出现的最大数据类型决定了最终结果的数据类型。
举个例子,float
与double
相乘,结果是double
。
3.16 Java没有sizeof
-
在C和C++中,sizeof()用来告诉你数据的字节数,为什么需要知道一个数据的字节数?这是因为在使用C与C++跨平台时,不同的数据类型在不同的机器上可能有不同的大小,所以需要使用sizeof()去知道这些数据到底有多大。这显然很麻烦与可怕。
-
Java由于其跨平台性,没有这方面的需求,因为这个问题在语言设计时,已经解决了。
小白的成长探索之路。
网友评论