对操作符的认识和笔记
操作符中一些值得注意的点
使用Java操作符
操作符作用于操作数,生成一个新值。另外有些操作符会改变自身的值,这被称为“副作用”。且几乎所有的操作符都只能操作“基本类型”。例外的操作符有“=”、“==”、和“!=”。这些操作符能操作所有的对象。除此之外,String还支持“+”和“+=”。而值得注意的是当System,out.println() 语句中包含“+”操作符表示字符串连接,并且当编译器观察到一个String后面紧跟着一个“+”,而“+”后又跟着1一个非String类型的元素时,就会尝试着将这个非String类型的元素转换为String。
赋值
赋值使用操作符“=”。对基本类型的赋值是很简单的。基本类型存储了实际的数值,而非指向一个对象的引用,所以在为其赋值的时候是直接将一个地方的内容复制到了另一个地方。但是在为对象赋值的时候情况发生了变化。对一个对象进行操作时我们真正操作的是对对象的引用。所以如果将一个对象赋值给另一个对象,实际上是将引用从一个地方复制到了另一个地方。比如对对象使用c=d,那么c和d都指向d所指向的对象。
class Integral {
float f;
}
public class E02_Aliasing {
public static void main(String[] args) {
Integral n1 = new Integral();
Integral n2 = new Integral();
n1.f = 9f;
n2.f = 47f;
print("1: n1.f: " + n1.f + ", n2.f: " + n2.f);
n1 = n2;
print("2: n1.f: " + n1.f + ", n2.f: " + n2.f);
n1.f = 27f;
print("3: n1.f: " + n1.f + ", n2.f: " + n2.f);
}
} /* Output:
1: n1.f: 9.0, n2.f: 47.0
2: n1.f: 47.0, n2.f: 47.0
3: n1.f: 27.0, n2.f: 27.0
*///:~
在如上所示的程序中,对象n2赋值给n1,接着修改了n1,这就导致了n2也被改变了,这是由于n1和n2包含的是相同的引用,指向相同的对象。(原本n1包含的对象的引用被覆盖导致这个对象丢失。)这种特殊的现象被称作“别名现象”,是Java操作对象的一种基本方式。在此例中避免别名问题可以这样改:
n1.f=n2.f;
这样保证了两个对象彼此独立。但是直接操作对象的域容易导致混乱。所以在设计程序时要格外注意对对象的赋值。
方法调用的别名问题
将一个对象传递给方法时,也会产生别名问题:
class Integral {
float f;
}
public class E03_Aliasing2 {
static void f(Integral y) { y.f = 1.0f; }
public static void main(String[] args) {
Integral x = new Integral();
x.f = 2.0f;
print("1: x.f: " + x.f);
f(x);
print("2: x.f: " + x.f);
}
} /* Output:
1: x.f: 2.0
2: x.f: 1.0
*///:~
关系操作符
关系操作符生成的是一个Boolean(布尔)结果。“==”和“!=”适用于所有的基本数据类型,而其它比较符不适用于Boolean类型。
测试对象的等价性
关系操作符==和!=也适用于所有对象,但这两个操作符时常会让人感到困惑。如下面代码所示:
public class Equivalence {
public static void main(String[] args){
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
} /*
false
true
*///
明明两个对象的实际内容是相同的,可结果却与我们预想的不一样,这是因为和!=比较的是对象的引用!而要想比较两个对象的实际内容就必须使用所有对象都适用的equals()方法。
但是值得注意的是如果是自己创建的类没有覆盖equals()方法时,与操作的结果是一样的。因为equals()方法的默认行为是比较引用。在之后会详细讨论覆盖以及如何定义equals()方法。
短路
当使用逻辑操作符时,我们会遇到一种“短路”现象。即一旦能够明确无误的确定整个表达式的值,就不再计算表达式余下部分了。
三元操作符
三元操作符也称为条件操作符,其表达式形式如下:
boolean-exp ? value0:value1
如果布尔表达式的结果为true,计算value0,而且这个计算结果也就是操作符最终产生的值。反之就计算value1。条件选择符与if-else完全不同,因为它会产生一个值。
类型转换
默认转换顺序(从小到大,向上转型):
byte short char ->int->long->double
byte short char 运算时转换为int ,运算中有long类型则结果是long类型,有double类型,结果是double类型。
byte short char 相互之间不转换,它们运算时先转换为int类型。
强制转换(从大到小,向下转型):
格式 目标数据类型 变量 = (目标数据类型) 数据;