Java之路:运算符

运算符

程序由许多语句组成,而语句组成的基本单位就是表达式与运算符。
【运算符分类】
按功能分:算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符、其他运算符。
按操作数数目:一元、二元、三元。

1、赋值运算符:=

它的意思是“取右值,把它复制给左值”。右值可以是任何常数、变量或表达式(只要它能生成一个值就行)。但左值必须是一个明确的、已命名的变量,即必须有一个物理空间可以存储等号右边的值。如下:

int a;
a = 4;	// 可以将常量赋给变量
//以下是错误
4 = a;	// 不能把任何东西赋给一个常数

注1:对基本数据类型的赋值是很简单的,基本类型存储了实际的值,而并非指向一个对象的引用,所以对其赋值的时候,是直接将一个地方的内容复制到了另一个地方。例如:a = b; 那么b的内容就复制给了a。若是修改a,b并不受影响。
注2:但是,在为对象赋值的时候,情况却不同。对一个对象进行操作时,我们真正操作的是对对象的引用。所以,若是“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方。这意味着,假如对对象使用c = d,那么c和d都指向原本只有d指向的那个对象。如下:

class Num {
	int num;
	Num(int num){
		this.num = num;
	}
}
public class Assignment {
	public static void main(String[] args) {
		Num a = new Num(1);
		Num b = new Num(2);
		System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num);
		a = b;	// a和b都指向原来b指向的对象
		System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num);
		a.num = 3;	// 因为此时a与b是指向同一对象,所以此时改变a所指向对象的值,b所指向的结果也改变
		System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num);
	}
}

【结果】
在这里插入图片描述
:在许多编程语言中,我们可能会期望a,b是相互独立的,但由于赋值运算符操作的是一个对象的引用,所以修改a的同时也改变了b!这是因为a和b包含的是相同的引用,它们指向相同的对象。(原本a包含的对对象的引用,是指向一个值为1的对象,但在对a赋值时,这个引用被覆盖了,也即丢失了;而那个不再被引用的值为1的对象会由“垃圾回收器”自动清理。)
这种特殊的现象通常称作“别名现象”,是Java操作对象的一种基本方式。而若要避免别名问题,则应该如下:
a.num = b.num;
这样就可以保持两个对象彼此独立,而不是将a和b绑定到相同的对象。

2、算术运算符:+ - * / %


(1)整数除法会直接去掉结果的小数位,而不是四舍五入。因为整形变量无法保存小数点后面的数据。
(2)Java中取余运算符%的操作数可以是负数和浮点数。而在C/C++中,取余运算符只能是整数。
(3)+运算符也可以连接两个字符串。

【示例】

public class Unary {
	public static void main(String[] args) {
		int x = 10/3;	// 取值为3,而不是3.33333...
		System.out.println("x = " + x);
		int a = 10%-3;	
		System.out.println("a = " + a);
		float b = 5.2f % 3.1f;
		System.out.println("b = " + b);
	}
}

【结果】
在这里插入图片描述

3、关系运算符:> < <= >= == !=

关系运算符生成的是一个boolean结果,它们计算的是操作数的之间的关系。
等于(==)和不等于(!=)适用于所有的基本数据类型。而其他比较符不适用于布尔类型,因为布尔类型只有true和false,大小没有意义。

测试对象的等价性【==、!=、equals()方法】

==、!=与equals()方法

【示例】

public class Equal {
	public static void main(String[] args) {
		int m = 3;
		int n = 3;
		Integer n1 = new Integer(47);
		Integer n2 = new Integer(47);
		System.out.println(m == n);
		System.out.println(n1 == n2);
		System.out.println(n1 != n2);
	}
}

【结果】
在这里插入图片描述
【结果分析】
等于(==)和不等于(!=)也适用于所有的对象,但在使用时一定要注意,对于基本数据类型,它们比较的是值(基本数据类型中存储的值)“本身”;对于引用数据类型,它们比较的变量对对象的引用(其所指向的对象在内存中的地址)。

(1)对于基本数据类型的变量,变量存储的是值“本身”。而所有关系运算符比较的就是值“本身”,而

   int m = 3; 
   int n = 3;

变量n和变量m都是直接存储的"3"这个数值,所以用==比较的时候结果是true。

(2)对于引用类型变量,引用类型的变量存储的并不是 “值”本身,而是于其关联的对象在内存中的地址。如:

	Integer n1 = new Integer(47);
	Integer n2 = new Integer(47);

引用类型变量n1中存储的是他所指向的对象在内存中的地址,而不是47这个值,同理,n2也是如此。

	System.out.println(n1 == n2);

当运行上面语句时,实际上比较的是n1和n2的引用(其指向的对象在内存中的地址)。然而,n1和n2对象的引用却是不同的,所以输出false。

【equals()方法】

equals方法是基类Object中的方法,因此对于所有的继承于Object的类都会有该方法。

equals()方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。

但equals()这个方法不适用于基本数据类型,基本类型直接使用==和!=即可。

public class Equal {
	public static void main(String[] args) {
		Integer n1 = new Integer(47);
		Integer n2 = new Integer(47);
		System.out.println(n1.equals(n2));
	}
}

【结果】

在这里插入图片描述
【结果分析】
不是说equals()比较的是引用嘛,那上面结果为什么对呢?这是因为,equals()默认确实是比较引用,但是Integer类中重写了equals()方法,使其比较引用对象的内容。
两个引用对象的内容都是47,所以结果是true。

假设你创建了自己的类,没有重写equals()方法,如下:

public class Equal {
	public static void main(String[] args) {
		Value v1 = new Value();
		Value v2 = new Value();
		v1.i = 100;
		v2.i = 100;
		System.out.println(v1.equals(v2));
	}
}

【结果】
在这里插入图片描述
【结果分析】
这是由于equals()的默认行为是比较引用,没有重写equals()方法,所以它无法比较引用对象的内容,只能默认比较对象的引用,引用不同,所以结果false。

4、逻辑运算符:与(&&)、或(||)、非(!)

与、或、非操作只能运用于布尔值,并返回一个布尔值。

(表达式1)&&(表达式2)	// 其中表达式1和表达式2必须的结果必须是布尔值
(表达式1)||(表达式2)
!(表达式)

:使用与(&&)、或(||)时,一旦能够明确无误地确定整个表达式的值,就不用再计算表达式余下的部分了,这种现象被称为“短路”。因此,整个逻辑表达式靠后的部分有可能不会被运算。

非短路:&,|
& 与 | 两边的表达式都要进行运算。

【分享一道Java面试题】

  1. &和&&、|和||的关系是怎么样?(Java面试题)
    答:
    对于“与操作”:有一个条件不满足,结果就是false。

普通与(&):所有的判断条件都要执行;短路与(&&):如果前面有条件已经返回了false,不再向后判断,那么最终结果就是false。

对于“或操作”:有一个条件满足,结果就是true。

对于普通或(|):所有的判断条件都要执行;

短路或(||):如果前面有条件返回了true,不再向后判断,那么最终结果就是true。

5、位运算符

在这里插入图片描述
在这里插入图片描述
其中,除 ~ 运算符外,其他位运算符都可以与=联合使用。&=、|=、^=、>>=、<<=、>>>=

运算符优先级

在这里插入图片描述
在这里插入图片描述

【一个小问题】

int i;;
int n;;;;;;;;;;;;;

上面两条语句合法吗?

答案是合法,事实上,由于多个Java语句可以处于同一行,那么int i ;;就可以解读为“int i;”这条语句和另外一个空语句“;”共处于一行之上。int i语句后面即使跟10个分号也合法。

猜你喜欢

转载自blog.csdn.net/qq_43555323/article/details/84726565