Loading... <div class="tip inlineBlock error"> 本文大部分内容摘录自[廖雪峰的官方网站](https://liaoxuefeng.com/) </div> # 浮点数运算 ## 浮点数计算的误差 <div class="tip inlineBlock share"> 这里编辑标签内容浮点数`0.1`在计算机中就无法精确表示,因为十进制的`0.1`换算成二进制是一个无限循环小数,很显然,无论使用`float`还是`double`,都只能存储一个`0.1`的近似值。但是,`0.5`这个浮点数又可以精确地表示。 --廖雪峰 </div> ```Java // 浮点数运算误差 public class Main { public static void main(String[] args) { double x = 1.0 / 10; double y = 1 - 9.0 / 10; // 观察x和y是否相等: System.out.println(x); //0.1 System.out.println(y); //0.100000024 } } ``` ### 正确比较 - 利用 Math.abs() 求差值的绝对值 廖使用 ```java // 比较x和y是否相等,先计算其差的绝对值: double r = Math.abs(x - y); // 再判断绝对值是否足够小: if (r < 0.00001) { // 可以认为相等 } else { // 不相等 } ``` 来进行比较,里边的''足够小''的差值需要根据实际情况来设定 - 利用 BigDecimal 类 暂且不考虑 ## 浮点数类型提升 如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型: ```java // 类型提升 public class Main { public static void main(String[] args) { int n = 5; double d = 1.2 + 24.0 / n; // 6.0 System.out.println(d); } } ``` ### 特例 - 复杂四则运算 ```java double d = 1.2 + 24 / 5; // 结果不是 6.0 而是 5.2 ``` 解决办法: ```java double d = 1.2 + 24.0 / 5; // 结果是 6.0 ``` ## 浮点数 强制转型为 整数 - 一般情况 浮点数小数部分被丢弃 ```java int a = (int) 114.514; //114 ``` - 转换后超出整型的最大值,则返回最大值 ```java int n4 = (int) 1.2e20; // 2147483647 ``` # 布尔运算 ## 短路运算 ```java // 短路运算 public class Main { public static void main(String[] args) { boolean b = 5 < 3; boolean result = b && (5 / 0 > 0); // 此处 5 / 0 不会报错 System.out.println(result); } } ``` <div class="tip inlineBlock share"> 如果没有短路运算,`&&`后面的表达式会由于除数为`0`而报错,但实际上该语句并未报错,原因在于与运算是短路运算符,提前计算出了结果`false`。 </div> **如果一个布尔运算的表达式能提前确定结果,则后续的计算不再执行,直接返回结果。** 因为`false && x`的结果总是`false`,无论`x`是`true`还是`false`,因此,与运算在确定第一个值为`false`后,不再继续计算,而是直接返回`false`。 ### 三元运算 三元运算符`b ? x : y` 它根据第一个布尔表达式的结果,分别返回后续两个表达式之一的计算结果 `true` -> x `false` -> y ```java // 三元运算 public class Main { public static void main(String[] args) { int n = -100; int x = n >= 0 ? n : -n; System.out.println(x); } } ``` <div class="tip inlineBlock error"> 上述x为整型而非布尔值 </div> # 字符串 ## 字符类型 字符类型`char`是基本数据类型,它是`character`的缩写。一个`char`保存一个Unicode字符: ```java char c1 = 'A'; char c2 = '中'; ``` 因为Java在内存中总是使用Unicode表示字符,所以,一个英文字符和一个中文字符都用一个`char`类型表示,它们都占用两个字节。要显示一个字符的Unicode编码,只需将`char`类型直接赋值给`int`类型即可: ```java int n1 = 'A'; // 字母“A”的Unicodde编码是65 int n2 = '中'; // 汉字“中”的Unicode编码是20013 ``` 还可以直接用转义字符`\u`+Unicode编码来表示一个字符: ```java // 注意是十六进制: char c3 = '\u0041'; // 'A',因为十六进制0041 = 十进制65 char c4 = '\u4e2d'; // '中',因为十六进制4e2d = 十进制20013 ``` ## 字符串的连接 可以使用`+`连接任意字符串和其他数据类型,如果用`+`连接字符串和其他数据类型,会将其他数据类型先自动转型为字符串,再连接 <div class="tip inlineBlock warning"> 前提是必须已有字符串 </div> <div class="panel panel-default collapse-panel box-shadow-wrap-lg"><div class="panel-heading panel-collapse" data-toggle="collapse" data-target="#collapse-79364f655968a9890ecc77628f5a6b7a71" aria-expanded="true"><div class="accordion-toggle"><span style="">解惑</span> <i class="pull-right fontello icon-fw fontello-angle-right"></i> </div> </div> <div class="panel-body collapse-panel-body"> <div id="collapse-79364f655968a9890ecc77628f5a6b7a71" class="collapse collapse-content"><p></p> ```java public class Main { public static void main(String[] args) { String s1 = "Hello"; String s2 = "world"; int a = 1; int b = 2; String s = a + b; //Type mismatch: cannot convert from int to String System.out.println(s); world! } } ``` 编译上述代码会报错`Type mismatch: cannot convert from int to String` 但是在里面加上一个字符串,就会自动转型了 ```java public class Main { public static void main(String[] args) { String s1 = "Hello"; String s2 = "world"; int a = 1; int b = 2; String s = "" + a + b; /* 其他可行示例 String s = a + "" + b; String s = s1 + a + b; String s = "" + (char)a + b; */ System.out.println(s); //12 } } ``` <p></p></div></div></div> ```java // 字符串连接 public class Main { public static void main(String[] args) { int age = 25; String s = "age is " + age; System.out.println(s); // age is 25 } } ``` ```java // 字符串连接 public class Main { public static void main(String[] args) { int a = 25; int b = 25; String s = "age is " + a + b; System.out.println(s); // age is 2525 } } ``` ## 特性:不可变 Java的字符串除了是一个引用类型外,还有个重要特点,就是字符串不可变。考察以下代码: ```java // 字符串不可变 public class Main { public static void main(String[] args) { String s = "hello"; System.out.println(s); // 显示 hello s = "world"; System.out.println(s); // 显示 world } } ``` 观察执行结果,难道字符串`s`变了吗?其实变的不是字符串,而是变量`s`的“指向”。 执行`String s = "hello";`时,JVM虚拟机先创建字符串`"hello"`,然后,把字符串变量`s`指向它: ![image.png](https://blog.acats.space/usr/uploads/2024/08/3916382048.png) 紧接着,执行`s = "world";`时,JVM虚拟机先创建字符串`"world"`,然后,把字符串变量`s`指向它: ![image.png](https://blog.acats.space/usr/uploads/2024/08/899262368.png) 原来的字符串`"hello"`还在,只是我们无法通过变量`s`访问它而已。因此,字符串的不可变是指字符串内容不可变。至于变量,可以一会指向字符串`"hello"`,一会指向字符串`"world"`。 理解了引用类型的“指向”后,试解释下面的代码输出: ```java // 字符串不可变 public class Main { public static void main(String[] args) { String s = "hello"; String t = s; s = "world"; System.out.println(t); // t是"hello"还是"world"? } } ``` ## 空值null 引用类型的变量可以指向一个空值`null`,它表示不存在,即该变量不指向任何对象。例如: ```java String s1 = null; // s1是null String s2 = s1; // s2也是null String s3 = ""; // s3指向空字符串,不是null ``` 注意要区分空值`null`和空字符串`""`,空字符串是一个有效的字符串对象,它不等于`null`。 # 数组 ## 数组是引用类型 其大小不可变 ```java // 数组 public class Main { public static void main(String[] args) { // 5位同学的成绩: int[] ns; ns = new int[] { 68, 79, 91, 85, 62 }; System.out.println(ns.length); // 5 ns = new int[] { 1, 2, 3 }; System.out.println(ns.length); // 3 } } ``` 对于数组`ns`来说,执行`ns = new int[] { 68, 79, 91, 85, 62 };`时,它指向一个5个元素的数组: ![image.png](https://blog.acats.space/usr/uploads/2024/08/2050684115.png) 执行`ns = new int[] { 1, 2, 3 };`时,它指向一个*新的*3个元素的数组: ![image.png](https://blog.acats.space/usr/uploads/2024/08/4158619310.png) 原有的5个元素的数组并没有改变,只是无法通过变量`ns`引用到它们而已。 ### 当数组元素是引用类型 ```java String[] names = { "ABC", "XYZ", "zoo" }; ``` 对于`String[]`类型的数组变量`names`,它实际上包含3个元素,但每个元素都指向某个字符串对象: ![image.png](https://blog.acats.space/usr/uploads/2024/08/1713662887.png)对`names[1]`进行赋值,例如`names[1] = "cat";`,效果如下: ![image.png](https://blog.acats.space/usr/uploads/2024/08/2064442582.png)原来`names[1]`指向的字符串`"XYZ"`并没有改变,仅仅是将`names[1]`的引用从指向`"XYZ"`改成了指向`"cat"`,其结果是字符串`"XYZ"`再也无法通过`names[1]`访问到了。 ```java // 数组 public class Main { public static void main(String[] args) { String[] names = {"ABC", "XYZ", "zoo"}; String s = names[1]; names[1] = "cat"; System.out.println(s); // s是"XYZ" } } ``` 当`s`是数组: ```Java public class Main { public static void main(String[] args) { String[] names = {"ABC", "XYZ", "zoo"}; String[] s = names; names[1] = "cat"; System.out.println(s[1]); // s[1]是"cat" } } ``` 因为`string[] s= names;`代表了`s`和`names`指向同一内存地址,当`names[1]`变为“cat”之后,内存地址就变为了“cat”,所以`s[1]`自然也是“cat”了。 最后修改:2024 年 09 月 05 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏