现在的位置: 首页 > 综合 > 正文

java学习笔记《java面向对象编程》——操作符

2018年01月25日 ⁄ 综合 ⁄ 共 4827字 ⁄ 字号 评论关闭

简介:对于不同的数据类型,有着不同的操作符,多数操作符只能操作基本数据类型的数据,例外的是 =、==、!=操作符,它们不仅能操作各种基本类型,还能操作各种引用类型。此外,+操作符不仅能操作除boolean类型以外的基本数据类型,还能操作java.lang.String类型。

多数操作符的结合性为从左到右。只有赋值操作符=及复合操作符(+=、-=和*=等)的结合性是从右到左。

一、整形操作符

整形操作符的操作元类型可以是byte、short、char、int和long。按操作元的多少可以分为一元操作符和二元操作符。在计算表达式时,如果有一个操作元是long型,那么结果也是long类型;否则不管操作元是byte、short或char型,运算结果都是int型。

一元整形操作符:-、~、++、--。++和--既可以作为前置操作符,也可以作为后置操作符,也就是说,它们既可以放在操作元前面(++x),也可以放在操作元后面(x++)。

二元整形操作符:数学运算操作符:+、-、*、/、%;位运算操作符:&、|、^(异或操作符)、>>>(逻辑右移位运算)、>>(算术右移位运算)、<<(左移位运算)。

二、浮点型操作符

多数整形操作符也可作为浮点型操作符,如:++、--、+、-、*、/和%等。同整形操作符相似,运算结果的类型和操作元中取值范围最大的类型一致。如果操作元中最大长度类型是float型,那么结果为float型。如果操作元中有一个或几个是double型,那么结果都是double型。

浮点运算不支持位运算,这和整数运算是不同的。Java浮点类型有两个特殊的值:负无穷大(-Infinity)和正无穷大(Infinity),它们可以用来表示无效的浮点运算的结果。正数除以0得正无穷大,负数除以0得负无穷大。

三、比较操作符和逻辑操作符

比较操作符:<、>、<=、>=、==、!=。逻辑操作符:&&、&、||、|、!。(&既可以作为逻辑操作符,也可以作为与操作符,看情况确定是哪个操作符,如果是两个boolean类型的变量则&是逻辑操作符,如果是两个整数类型的变量则&是与操作符)

<、>、<=、>=操作符的操作元只能是整数类型和浮点类型。==和!=操作符的操作元既可以是基本类型,也可以是引用类型。

&&和&均为与操作符,||和|均为或操作符,它们的操作元只能是布尔表达式。布尔表达式是指运算结果为boolean类型的表达式。

&&和||是短路操作符,&和|是非非短路操作符,它们的区别是:对于短路操作符,如果能根据操作符左边的布尔表达式就能推算出整个表达式的布尔值,将不执行操作符右边的布尔表达式;对于非短路操作符,始终会执行操作符两边的布尔表达式。

在某些情况下,短路操作符有助于提高程序代码的安全性。例如:

public void sayHello(People person){
	if(person!=null&person.name!=null){
		System.out.println("Hello: "+person.name);
	}
}

假如传给sayHello()方法的person参数为null,那么执行if表达式中的person.name就会抛出NullPointerException异常。如果把非短路操作符&改为短路操作符&&,就能避免这一问题。

public void sayHello(People person){
	if(person!=null&&person.name!=null){
		System.out.println("Hello: "+person.name);
	}
}

假如传给sayHello()方法的person参数为null,那么person!=null表达式的值为false,整个if表达式为false,此时person.name!=null表达式不会被执行,因此避免了NullPointerException异常。

!是一元操作符,操作元也必须是布尔表达式。当布尔表达式的值为true时,运算结果为false;当布尔表达式为false时,运算结果为true。

四、三元操作符 ?:

在Java语言中有一个特殊的三元操作符?:,它的语法形式为:

布尔表达式? 表达式1:表达式2

如果布尔表达式的值为true,就执行表达式1再返回表达式1的值,否则执行表达式2再返回表达式2的值。

以上的操作符等价于以下的if......else语句,前者使程序代码更加简洁。

五、字符串连接操作符 +

有两种情况:

如果+操作符中有一个操作元为String类型,则另一个操作元可以是任意类型(包括基本类型和引用类型),不过该操作元将被转换成字符串。当一个操作元为引用类型,就调用所引用对象的toString()方法来获得字符串。

如果+操作符的两个操作元都不是String类型,那么+操作符的两个操作元必须都是除boolean以外的基本数据类型,此时+作为数字加法操作符处理。

对于包含多个+操作符的表达式,Java根据+的左结合性特点,从左边开始计算表达式。根据操作元的类型来决定+是字符串连接操作符还是数字加法操作符。

值得注意的是,除了+能用于字符串的连接以外,其他操作符都不支持String类型的操作元。

六、操作符==与对象的equals()方法

操作符==用来比较两个操作元是否相等,这两个操作元既可以是基本类型,也可以是引用类型。

当==操作符两边都是引用类型变量时,这两个引用变量都必须引用同一个对象,结果才为true。

对于引用类型变量,Java编译器根据变量被显示声明的类型去编译。当==用于比较引用类型变量时,==两边的变量被显示声明的类型必须是同种类型或有继承关系,即位于继承树的同一个继承分支上,否则编译出错。而在运行时,Java虚拟机将根据两边的引用变量实际引用的对象进行比较。操作类型也是引用类型,可以用==进行比较。

对象的equals()方法是在Object类中定义的方法。

public boolean equals(Object obj){
	if(this==obj)return true;
	else return false;
}

这样看来,==和Object类中的equals()方法是相同的。

JDK中有一些类覆盖了Object类的equals()方法,它们的比较规则是:如果两个对象的类型一致,并且内容一致,则返回true。这些类包括:java.io.File、java.util.Date、java.lang.String、包装类(如java.lang.Integer和java.lang.Double类)。

在实际运用中,比较字符串是否相等时,通常都是按照内容比较才会有意义,因此该调用String类的equals()方法,而不是采用==操作符。在用户自定义的类中也可以覆盖Object类的equals()方法,重新定义比较规则。

七、instanceof操作符

instanceof操作符用于判断一个引用类型所引用的对象是否是另一个类的实例。一个类的实例包括类本身的实例,以及所有直接或间接的子类的实例。instanceof操作符左边的操作元是一个引用类型,右边的操作元是一个类名或接口名,返回值类型为boolean型。

对于引用类型变量,Java编译器只根据变量被显示声明的类去编译。instanceof左边操作元被显示声明的类型与右边操作元必须是同种的类或有继承关系,即位于继承树的同一个继承分支上,否则编译出错。在运行时,将根据左边操作元实际引用的对象来判断。(在这一点上和==一样)
假定Animal类是非抽象类,允许实例化,以下isInstanceOfAnimal()方法的判断规则为:只有当参数obj引用Animal类本身的实例,而不是它的子类Dog或Cat的实例时,才返回true。

public boolean isIntanceOfAnimal(Object obj){
	return obj instanceof Animal && !(obj instanceof Dog)&&!(obj instanceof Cat);
}

instanceof也可用于数组类型,如:boolean b1=new int [4] instanceof long[];//编译出错,instanceof两边操作元的类型不一致;boolean b2=new int[4] instanceof int[];//合法,b2的值为true
八、变量的赋值和类型转换

= 操作符是使用最频繁的二元操作符,它能够把右边操作元的值赋给左边的操作元,并且右边操作元的值作为运算结果。

在同种类型的变量之间赋值时,不需要进行类型的转换。当在不同类型的变量之间赋值时,或者将一个直接数赋给与它不同类型的变量时,需要类型转换。

类型转换可分为自动类型转换和强制类型转换两种。自动转换是指运行时,Java虚拟机自动把一种类型转换成另一种类型。强制类型转换是指在程序中显示的进行类型转换。

值得注意的是,在进行自动或强制类型转换时,被转换的变量本身没有任何变化。

1、基本数据类型转换

整型、浮点型、字符型数据可以进行混合运算。当类型不一致时,需要进行类型转换。

从低位类型到高位类型会进行自动转换,而从高位类型到低位类型需要进行强制类型的转换。值得注意的是,boolean类型不能与其他的基本类型进行类型转换。

A、自动类型转换

(1)表达式中不同类型的数据先自动转换为同一种类型,然后进行运算。

当表达式中存在double类型时,所有操作元自动转换为double类型,表达式的值为double类型。

否则,当表达式中存在float类型时,所有操作元自动转换为float类型,表达式的值为float类型。

否则,当表达式中存在long类型时,所有操作元自动转换为long类型,表达式的值为龙类型。

否则,把所有的操作元自动转换为int类型,表达式的值为int类型。

(2)在进行赋值运算时,也会进行低位到高位的自动类型转换。
赋值运算的自动类型转换优先级如下:

byte→short(char)→int→long→float→double

在给方法传递参数时,也会出现类型自动转换的情况,转换规则与赋值运算的自动转换规则相同。

从低位到高位的自动转换一般来说是安全的,不会出现数据溢出或精度下降的情况,因为低位类型的取值范围在高位类型的取值范围之内。在个别情况下,自动转换会导致数据溢出现象。

int a=Integer.MAX_VALUE; int b=a+20;

此时,编程人员应该事先预见这种可能性,然后选用合适的高位数据类型。

B、强制类型转换

如果把高位类型赋值给低位类型,就必须进行强制类型转换,否则编译会出错。

short和char类型的二进制数的位数都是16,由于两者的取值范围不一致,在short变量和char变量之间的赋值总需要强制类型转换。如果把char类型直接数赋给short类型或者比它优先级低(byte)类型变量,或者把int类型直接数赋给比它优先级低的变量,那么只要直接数在变量所属类型的取值范围之内,就允许自动类型转换,否则需要强制类型转换。值得注意的是:这只是将直接数赋值给变量时的规则,如果是变量之间的赋值或者是表达式赋值给变量时,这些规则不管用。

强制类型转换有可能会导致数据溢出或精度的下降,应该尽量避免使用强制类型转换。

2、引用类型的类型转换

在引用类型的变量之间赋值时,子类给直接或间接父类赋值,会自动进行类型转换。父类直接或间接子类赋值,需要进行强制类型转换。对于引用类型变量,Java编译器只根据变量被显示声明的类型去编译。在引用类型变量之间赋值时,=操作符两边的变量被显示声明的类型必须是同种类型或有继承关系,即位于继承树的同一个继承分支上,否则编译报错。在运行时,Java虚拟机将根据引用变量实际引用的对象进行类型转换。(这一点和==、instanceof操作符是一致的)

抱歉!评论已关闭.