一、关系操作符
关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系。如果关系是真实的,关系表达式会生成的true;如果关系不真实,则生成false。关系操作符包括小于(<)、大于(>)、小于或等于(<=)、大于或等于(>=)、等于(==)以及不等于(!=)。等于和不等于适用于所有的基本数据类型,而其他比较符不适用于boolean类型。因为boolean值只有为true或false,“大于”和“小于”没有实际意义。
(1)测试对象的等价性
关系操作符==和!=也适用于所有对象,但这两个操作符通常会使第一次接触java的程序员感到迷惑。下面是一个例子:
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);
}
}
语句System.out.println(n1 == n2)将打印出括号的比较式的布尔值结果。可能认为输出结果肯定是true,再试false,因为两个Integer对象都是相同的。但是尽管对象的内容相同,然而对象的引用却是不同的,而==和!=比较的就是对象的引用。所以输出结果实际上先是false,再是true。
如果想比较两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用于特殊方法equals()。但这个方法不适用于“基本类型”,基本类型直接使用==和!=即可。
public class EqualsMethod {
public static void main(String[] args) {
Integer n1=new Integer(47);
Integer n2=new Integer(47);
System.out.println(n1.equals(n2));
}
}
结果正如我们所预料的那样。但事情并不总是这么简单。假设你创建了自己的类,就像下面这样:
class Value{
int i;
}
public class EqualsMethod2 {
public static void main(String[] args) {
Value v1=new Value();
Value v2=new Value();
v1.i=v2.i=100;
System.out.println(v1.equals(v2));
}
}
事情再次变得费解了:结果又是false。这是由于equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。大多数java类库都实现了equals()方法,以便用来比较对象的内容,而非比较对象的引用。
二、逻辑操作符
逻辑操作符“与”(&&)、“或”(||)、“非”(!)能根据参数的逻辑关系,生成一个布尔值(true或false)。下面这个例子就使用了关系操作符和逻辑操作符。
import java.util.Random;
public class Bool {
public static void main(String[] args) {
Random r = new Random(47);
int i = r.nextInt(100);
int j = r.nextInt(100);
System.out.println("i=" + i);
System.out.println("j=" + j);
System.out.println("i>j is" + (i > j));
System.out.println("i<j is" + (i < j));
System.out.println("i<=j is" + (i <= j));
System.out.println("i>=j is" + (i >= j));
System.out.println("i==j is" + (i == j));
System.out.println("i!=j is" + (i != j));
}
}
注意,如果在应该使用String值的地方使用了boolean值,布尔值会自动转换成适当的文本形式。在上述程序中,可将整数类型替换成除布尔型以外的其他任何基本数据类型。但要注意,对浮点数的比较是非常严格的。即使一个数仅在小数部分与另一个数存在极微小的差异,仍然认为它们是“不相等”的。即使一个数只比零大一点点,它仍然是“非零”值。
(1)短路
当使用逻辑操作符时,我们会遇到一种“短路”现象。即一旦能够明确无误地确定整个表达式的值,就不再计算表达式余下的部分了。因此,整个逻辑表达式靠后的部分有可能不会被运算。例如:
public class ShortCircuit {
static boolean test1(int val) {
System.out.println("test1(" + val + ")");
System.out.println("result:" + (val < 1));
return val < 1;
}
static boolean test2(int val) {
System.out.println("test2(" + val + ")");
System.out.println("result:" + (val < 2));
return val < 2;
}
static boolean test3(int val) {
System.out.println("test3(" + val + ")");
System.out.println("result:" + (val < 3));
return val < 3;
}
public static void main(String[] args) {
boolean b = test1(0) && test2(2) && test3(2);
System.out.println("expression is " + b);
}
}
每个测试都会比较参数,并返回true或false。它也会打印信息告诉你正在调用测试。这些测试都作用于下面这个表达式:
test1(0) && test2(2) && test3(2)
你会很自然的认为所有这三个测试都会得以执行。但输出显示却并非这样。第一个测试生成结果true,所以表达式计算会继续下去。然而,第二个测试产生了一个false结果。由于这意味着整个表达式肯定为false,所以没有必要继续计算剩余的表达式,那样只是浪费。“短路”一词的由来正源于此。事实上,如果所有的逻辑表达式都有一部分不必计算,那将获得潜在的性能提升。
三、三元操作符
三元操作符也称为条件操作符,它显得比较特别,因为它有三个操作数;但它确实属于操作符的一种,因为它最终也会生成一个值。其表达式形式:boolean-exp? value0:value1
如果boolean-exp(布尔表达式)的结果为true,就计算 value0,而且这个计算结果也就是操作符最终产生的值。如果boolean-exp的结果为false,就计算value1,同样,它的结果也就成为操作符最终产生的值。
条件操作符与if-else完全不同,因为它会产生一个值。下面是这两者进行比较的示例:
public class TernaryIfElse {
static int ternary(int i) {
return i < 10 ? i * 100 : i * 10;
}
static int standardIfElse(int i) {
if (i < 10)
return i * 100;
else
return i * 10;
}
public static void main(String[] args) {
System.out.println(ternary(9));
System.out.println(ternary(10));
System.out.println(standardIfElse(9));
System.out.println(standardIfElse(10));
}
}
可以看出,上面的ternary()中的代码与standardIfElse()中不用三元操作符的代码相比,显得更加紧凑;但standardIfElse()更易理解,而且不需要太多的录入。所以在选择使用三元操作符时,请务必仔细考虑。
四、字符串操作符 + 和 +=
这个操作符在java中有一项特殊用途:连接不同的字符串。字符串操作符有一些很有趣的行为。如果表达式以一个字符串起头,那么后续所有操作数都必须是字符串型(编译器会把双引号内的字符序列自动转成字符串):
public class StringOperators {
public static void main(String[] args) {
int x = 0, y = 1, z = 2;
String s = " x, y, z ";
System.out.println(s + x + y + z);
System.out.println(x + s);
s += "(summed) = ";
System.out.println(s + (x + y + z));
System.out.println("" + x);
}
}
请注意,第一个打印语句的输出是012而不是3,而3正式将这些整数求和之后应该得到的结果,之所以出现这种情况,是因为java编译器会将x、y和z转换成它们的字符串形式,然后连接这些字符串,而不是先把它们加到一起。第二个打印语句把先导的变量转换成String,因此这个字符串转换将不依赖于第一个变量的类型。最后,看到+=操作符将一个字符串追加到了s上,并且使用了括号来控制表达式的赋值顺序,以使得int类型的变量在显示之前确实进行了求和操作。
请注意main()中的最后一个示例:有时会看到这种一个空的String后面跟随+和一个基本类型变量,以此作为不调用更加麻烦的显示方法(Integer.toString())而执行字符串转换的方式。
五、类型转换操作符
类型转换(cast)的愿意是“模型铸造”。在适当的时候,java会将一种数据类型自动转换成另一种。例如,假设我们为某浮点变量赋以一个整数值,编译器会将int自动转换成float。类型转换运算允许我们显式地进行这种类型的转换,或者在不能自动进行转换的时候强制进行类型转换。
要想执行类型转换,需要将希望得到的数据类型置于圆括号内,放在要进行类型转换的值得左边,可以在下面的示例中看到它:
public class Casting {
public static void main(String[] args) {
int i = 200;
long lng = i;
long lng2 = (long) 100;
short a = (short) lng;
}
}
正如所看到的,既可对数值进行类型转换,亦可对变量进行类型转换。请注意,这里可能会引入“多余的类型”,例如,编译器在必要的时候会自动进行int值到long值的提升。但是你仍然可以做这样“多余的”事,以提醒自己需要注意,也可以使代码更清楚。在其他情况下,可能只有先进行类型转换,代码编译才能通过。
在C和C++中,类型转换有时会让人头痛。但是在java中,类型转换则是一种比较安全的操作。然而,如果要执行一种名为窄化转换(narrowing conversion)的操作(也就是说,将能容纳更多信息的数据类型转换成无法容纳那么多信息的类型),就有可能面临信息丢失的危险。此时编译器会强制我们进行类型转换,这实际上是说:“这可能是一件危险的事情,如果无论如何要这么做,必须显式地进行类型转换。”而对于扩展转换(videning conversion),则不必显式地进行类型转换,因为新类型肯定能容纳原来类型的信息,不会造成任何信息的丢失。
java允许我们把任何基本数据类型转换成别的基本数据类型,但布尔型除外,后者根本不允许进行任何类型的转换处理。“类”数据类型不允许进行类型转换。为了将一种类转换成另一种,必须采用特殊的方法。
(1)截尾和舍入
在执行窄化转换时,必须注意截尾与舍入的问题。例如,如果将一个浮点值转换为整型值,java会如何处理呢?例如,将29.7转换为int,结果是30还是29?例如:
public class CastingNumbers {
public static void main(String[] args) {
double above = 0.7, below = 0.4;
float fabove = 0.7f, fbelow = 0.4f;
System.out.println("(int)above:" + (int) above);
System.out.println("(int)below:" + (int) below);
System.out.println("(int)fabove:" + (int) fabove);
System.out.println("(int)fbelow:" + (int) fbelow);
}
}
因此答案是在将float和double转型为整型时,总是对该数字执行截尾。如果想要得到舍入的结果,就需要使用java.lang.Math中的round()方法:
public class RoundingNumbers {
public static void main(String[] args) {
double above = 0.7, below = 0.4;
float fabove = 0.7f, fbelow = 0.4f;
System.out.println("(int)above:" + Math.round(above));
System.out.println("(int)below:" + Math.round(below));
System.out.println("(int)fabove:" + Math.round(fabove));
System.out.println("(int)fbelow:" + Math.round(fbelow));
}
}
由于round()是java.lang的一部分,因此在使用它时不需要额外地导入。
(2)提升
如果对基本数据类型执行算术或按位运算,大家会发现,只要类型比int小(即char、byte或者short),那么在运算之前,这些值会自动转换成int。这样一来,最终生成的结果就是int类型。如果想把结果赋值给较小的类型,就必须使用类型转换(既然把结果赋给较小的类型,就可能出现信息丢失)。通常,表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。如果将一个float值与一个double值相乘,结果就是double;如果将一个int和long值相加,则结果为long。
来源:CSDN
作者:游王子
链接:https://blog.csdn.net/qq_40298351/article/details/104003822