湖州 网站建设网站建设分金手指专业十六
湖州 网站建设,网站建设分金手指专业十六,一起做网站17广州,物流网站建设费用本章概要
关系运算符 测试对象等价 逻辑运算符 短路 字面值常量 下划线指数计数法 位运算符
关系运算符
关系运算符会通过产生一个布尔#xff08;boolean#xff09;结果来表示操作数之间的关系。如果关系为真#xff0c;则结果为 true#xff0c;如果关系为假#xf…本章概要
关系运算符 测试对象等价 逻辑运算符 短路 字面值常量 下划线指数计数法 位运算符
关系运算符
关系运算符会通过产生一个布尔boolean结果来表示操作数之间的关系。如果关系为真则结果为 true如果关系为假则结果为 false。关系运算符包括小于 大于 小于或等于 大于或等于 等于 和不等于 。 和 ! 可用于所有基本类型但其他运算符不能用于基本类型 boolean因为布尔值只能表示 true 或 false所以比较它们之间的“大于”或“小于”没有意义。
测试对象等价
关系运算符 和 ! 同样适用于所有对象之间的比较运算但它们比较的内容却经常困扰 Java 的初学者。下面是代码示例
// operators/Equivalence.java
public class Equivalence {public static void main(String[] args) {Integer n1 47;Integer n2 47;System.out.println(n1 n2);System.out.println(n1 ! n2);}
}输出结果
true
false表达式 System.out.println(n1 n2) 将会输出比较的结果。因为两个 Integer 对象相同所以先输出 true再输出 false。但是尽管对象的内容一样对象的引用却不一样。 和 ! 比较的是对象引用所以输出实际上应该是先输出 false再输出 true译者注如果你把 47 改成 128那么打印的结果就是这样因为 Integer 内部维护着一个 IntegerCache 的缓存默认缓存范围是 [-128, 127]所以 [-128, 127] 之间的值用 和 ! 比较也能能到正确的结果但是不推荐用关系运算符比较具体见 JDK 中的 Integer 类源码。
那么怎么比较两个对象的内容是否相同呢你必须使用所有对象不包括基本类型中都存在的 equals() 方法下面是如何使用 equals() 方法的示例
// operators/EqualsMethod.java
public class EqualsMethod {public static void main(String[] args) {Integer n1 47;Integer n2 47;System.out.println(n1.equals(n2));}
}输出结果:
true上例的结果看起来是我们所期望的。但其实事情并非那么简单。下面我们来创建自己的类
// operators/EqualsMethod2.java
// 默认的 equals() 方法没有比较内容
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上例的结果再次令人困惑结果是 false。原因 equals() 的默认行为是比较对象的引用而非具体内容。因此除非你在新类中覆写 equals() 方法否则我们将获取不到想要的结果。不幸的是在学习 复用Reuse 章节后我们才能接触到“覆写”Override并且直到集合主题才能知道定义 equals() 方法的正确方式但是现在明白 equals() 行为方式也可能为你节省一些时间。
大多数 Java 库类通过覆写 equals() 方法比较对象的内容而不是其引用。
逻辑运算符
每个逻辑运算符 AND、||OR和 !非根据参数的逻辑关系生成布尔值 true 或 false。下面的代码示例使用了关系运算符和逻辑运算符
// operators/Bool.java
// 关系运算符和逻辑运算符
import java.util.*;
public class Bool {public static void main(String[] args) {Random rand new Random(47);int i rand.nextInt(100);int j rand.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));// 将 int 作为布尔处理不是合法的 Java 写法//- System.out.println(i j is (i j));//- System.out.println(i || j is (i || j));//- System.out.println(!i is !i);System.out.println((i 10) (j 10) is ((i 10) (j 10)) );System.out.println((i 10) || (j 10) is ((i 10) || (j 10)) );}
}输出结果 在 Java 逻辑运算中我们不能像 C/C 那样使用非布尔值 而仅能使用 AND、 OR、 NOT。上面的例子中我们将使用非布尔值的表达式注释掉了你可以看到表达式前面是 //-。但是后续的表达式使用关系比较生成布尔值然后对结果使用了逻辑运算。请注意如果在预期为 String 类型的位置使用 boolean 类型的值则结果会自动转为适当的文本格式即 “true” 或 “false” 字符串。
我们可以将前一个程序中 int 的定义替换为除 boolean 之外的任何其他基本数据类型。但请注意float 类型的数值比较非常严格只要两个数字的最小位不同则两个数仍然不相等只要数字最小位是大于 0 的那么它就不等于 0。
短路
逻辑运算符支持一种称为“短路”short-circuiting的现象。整个表达式会在运算到可以明确结果时就停止并返回结果这意味着该逻辑表达式的后半部分不会被执行到。代码示例
// operators / ShortCircuit.java
// 逻辑运算符的短路行为
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。同时控制台也会在方法执行时打印他们的执行状态。 下面的表达式
test10 test22 test32可能你的预期是程序会执行 3 个 test 方法并返回。我们来分析一下第一个方法的结果返回 true因此表达式会继续走下去。紧接着第二个方法的返回结果是 false。这就代表这整个表达式的结果肯定为 false所以就没有必要再判断剩下的表达式部分了。
所以运用“短路”可以节省部分不必要的运算从而提高程序潜在的性能。
注关于“短路”的更多测试见https://blog.csdn.net/GXL_1012/article/details/130119901
通常当我们向程序中插入一个字面值常量Literal时编译器会确切地识别它的类型。当类型不明确时必须辅以字面值常量关联来帮助编译器识别。代码示例
// operators/Literals.java
public class Literals {public static void main(String[] args) {int i1 0x2f; // 16进制 (小写)System.out.println(i1: Integer.toBinaryString(i1));int i2 0X2F; // 16进制 (大写)System.out.println(i2: Integer.toBinaryString(i2));int i3 0177; // 8进制 (前导0)System.out.println(i3: Integer.toBinaryString(i3));char c 0xffff; // 最大 char 型16进制值System.out.println(c: Integer.toBinaryString(c));byte b 0x7f; // 最大 byte 型16进制值 01111111;System.out.println(b: Integer.toBinaryString(b));short s 0x7fff; // 最大 short 型16进制值System.out.println(s: Integer.toBinaryString(s));long n1 200L; // long 型后缀long n2 200l; // long 型后缀 (容易与数值1混淆)long n3 200;// Java 7 二进制字面值常量:byte blb (byte) 0b00110101;System.out.println(blb: Integer.toBinaryString(blb));short bls (short) 0B0010111110101111;System.out.println(bls: Integer.toBinaryString(bls));int bli 0b00101111101011111010111110101111;System.out.println(bli: Integer.toBinaryString(bli));long bll 0b00101111101011111010111110101111;System.out.println(bll: Long.toBinaryString(bll));float f1 1;float f2 1F; // float 型后缀float f3 1f; // float 型后缀double d1 1d; // double 型后缀double d2 1D; // double 型后缀// (long 型的字面值同样适用于十六进制和8进制 )}
}输出结果: 在文本值的后面添加字符可以让编译器识别该文本值的类型。对于 Long 型数值结尾使用大写 L 或小写 l 皆可不推荐使用 l因为容易与阿拉伯数值 1 混淆。大写 F 或小写 f 表示 float 浮点数。大写 D 或小写 d 表示 double 双精度。
十六进制以 16 为基数适用于所有整型数据类型由前导 0x 或 0X 表示后跟 0-9 或 a-f 大写或小写。如果我们在初始化某个类型的数值时赋值超出其范围那么编译器会报错不管值的数字形式如何。在上例的代码中char、byte 和 short 的值已经是最大了。如果超过这些值编译器将自动转型为 int并且提示我们需要声明强制转换强制转换将在本章后面定义意味着我们已越过该类型的范围界限。
八进制以 8 为基数由 0~7 之间的数字和前导零 0 表示。
Java 7 引入了二进制的字面值常量由前导 0b 或 0B 表示它可以初始化所有的整数类型。
使用整型数值类型时显示其二进制形式会很有用。在 Long 型和 Integer 型中这很容易实现调用其静态的 toBinaryString() 方法即可。 但是请注意若将较小的类型传递给 Integer.toBinaryString() 时类型将自动转换为 int。
字面值常量
下划线
Java 7 中有一个深思熟虑的补充我们可以在数字字面量中包含下划线 _以使结果更清晰。这对于大数值的分组特别有用。代码示例
// operators/Underscores.java
public class Underscores {public static void main(String[] args) {double d 341_435_936.445_667;System.out.println(d);int bin 0b0010_1111_1010_1111_1010_1111_1010_1111;System.out.println(Integer.toBinaryString(bin));System.out.printf(%x%n, bin); // [1]long hex 0x7f_e9_b7_aa;System.out.printf(%x%n, hex);}
}输出结果:
3.41435936445667E8
101111101011111010111110101111
2fafafaf
7fe9b7aa下面是合理使用的规则
仅限单 _不能多条相连。数值开头和结尾不允许出现 _。F、D 和 L的前后禁止出现 _。二进制前导 b 和 十六进制 x 前后禁止出现 _。
[1] 注意 %n的使用。熟悉 C 风格的程序员可能习惯于看到 \n 来表示换行符。问题在于它给你的是一个“Unix风格”的换行符。此外如果我们使用的是 Windows则必须指定 \r\n。这种差异的包袱应该由编程语言来解决。这就是 Java 用 %n 实现的可以忽略平台间差异而生成适当的换行符但只有当你使用 System.out.printf() 或 System.out.format() 时。对于 System.out.println()我们仍然必须使用 \n如果你使用 %nprintln() 只会输出 %n 而不是换行符。
指数计数法
指数总是采用一种我认为很不直观的记号方法:
// operators/Exponents.java
// e 表示 10 的几次幂
public class Exponents {public static void main(String[] args) {// 大写 E 和小写 e 的效果相同:float expFloat 1.39e-43f;expFloat 1.39E-43f;System.out.println(expFloat);double expDouble 47e47d; // d 是可选的double expDouble2 47e47; // 自动转换为 doubleSystem.out.println(expDouble);}
}输出结果:
1.39E-43
4.7E48在科学与工程学领域e 代表自然对数的基数约等于 2.718 Java 里用一种更精确的 double 值 Math.E 来表示自然对数。指数表达式 “1.39 x e-43”意味着 “1.39 × 2.718 的 -43 次方”。然而自 FORTRAN 语言发明后人们自然而然地觉得e 代表 “10 的几次幂”。这种做法显得颇为古怪因为 FORTRAN 最初是为科学与工程领域设计的。
理所当然它的设计者应对这样的混淆概念持谨慎态度。但不管怎样这种特别的表达方法在 CC 以及现在的 Java 中顽固地保留下来了。所以倘若习惯 e 作为自然对数的基数使用那么在 Java 中看到类似“1.39e-43f”这样的表达式时请转换你的思维从程序设计的角度思考它它真正的含义是 “1.39 × 10 的 -43 次方”。
注意如果编译器能够正确地识别类型就不必使用后缀字符。对于下述语句
long n3 200;它并不存在含糊不清的地方所以 200 后面的 L 大可省去。然而对于下述语句
float f4 1e-43f; //10 的幂数编译器通常会将指数作为 double 类型来处理所以假若没有这个后缀字符 f编译器就会报错提示我们应该将 double 型转换成 float 型。
位运算符
位运算符允许我们操作一个整型数字中的单个二进制位。位运算符会对两个整数对应的位执行布尔代数从而产生结果。
位运算源自 C 语言的底层操作。我们经常要直接操纵硬件频繁设置硬件寄存器内的二进制位。Java 的设计初衷是电视机顶盒嵌入式开发所以这种底层的操作仍被保留了下来。但是你可能不会使用太多位运算。
若两个输入位都是 1则按位“与运算符” 运算后结果是 1否则结果是 0。若两个输入位里至少有一个是 1则按位“或运算符” | 运算后结果是 1只有在两个输入位都是 0 的情况下运算结果才是 0。若两个输入位的某一个是 1另一个不是 1那么按位“异或运算符” ^ 运算后结果才是 1。按位“非运算符” ~ 属于一元运算符它只对一个自变量进行操作其他所有运算符都是二元运算符。按位非运算后结果与输入位相反。例如输入 0则输出 1输入 1则输出 0。
位运算符和逻辑运算符都使用了同样的字符只不过数量不同。位短所以位运算符只有一个字符。位运算符可与等号 联合使用以接收结果及赋值| 和 ^ 都是合法的由于 ~ 是一元运算符所以不可与 联合使用。
我们将 Boolean 类型被视为“单位值”one-bit value所以它多少有些独特的地方。我们可以对 boolean 型变量执行与、或、异或运算但不能执行非运算大概是为了避免与逻辑“非”混淆。对于布尔值位运算符具有与逻辑运算符相同的效果只是它们不会中途“短路”。此外针对布尔值进行的位运算为我们新增了一个“异或”逻辑运算符它并未包括在逻辑运算符的列表中。在移位表达式中禁止使用布尔值原因将在下面解释。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/85260.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!