读书笔记 | 《Think in Java》Ⅲ 操作符

Ⅲ 操作符

---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

  • 在对不同的基本类型进行算术运算或者是按位运算时,表达式中出现的最大数据类型决定了最终结果的数据类型。 举个例子,floatdouble相乘,结果是double

3.16 Java没有sizeof
  • 在C和C++中,sizeof()用来告诉你数据的字节数,为什么需要知道一个数据的字节数?这是因为在使用C与C++跨平台时,不同的数据类型在不同的机器上可能有不同的大小,所以需要使用sizeof()去知道这些数据到底有多大。这显然很麻烦与可怕。

  • Java由于其跨平台性,没有这方面的需求,因为这个问题在语言设计时,已经解决了。

小白的成长探索之路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值