前言:

本篇是接着上一篇更新的,如果没有阅读上一篇的话,可以查阅或回顾一下。

1、收入囊中篇---Java基础必备知识(一)

2、收入囊中篇---Java程序基础(二)


Java程序基础目录

1、Java的基本结构

2、变量和数据结构

  • 变量
  • 基本数据类型
  • 整型
  • 浮点型
  • 布尔类型
  • 字符类型
  • 常量
  • var关键字
  • 变量的作用范围
  • 小结

3、整数运算(本篇内容)

  • 溢出
  • 简洁的运算符
  • 自增/自减
  • 移位运算
  • 位运算
  • 运算优先级
  • 类型自动提升与强制转型
  • 小结

4、浮点数运算(本篇内容)

  • 类型提升
  • 溢出
  • 强制转型
  • 练习:
  • 小结

5、布尔运算

  • ```
  • 短路运算
  • 三元运算符
  • 练习:
  • 小结 ```

6、字符和字符串

  • ```
  • 字符类型
  • 字符串类型
  • 字符串连接
  • 多行字符串
  • 不可变特性
  • 空值null
  • 练习:
  • 小结 ```

7、数组类型

  • ```
  • 字符串数组
  • 小结 ```

3、整数运算

Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号。四则运算规则和初等数学一致。例如:

//四则运算
public class Main {public static void main(String[] args) {int i = (100 + 200) * (99 - 88); // 3300int n = 7 * (5 + (i - 9)); // 23072System.out.println(i);System.out.println(n);}
}//从左往右先乘除,后加减依次进行

  • 整数的数值表示不但是精确的,而且整数运算永远是精确的,即使是除法也是精确的,因为两个整数相除只能得到结果的整数部分:
int x = 12345 / 67;   // 184 ,整型只能够得到整数

  • 求余运算使用%
int y = 12345 % 67;    // 12345÷67的余数是17

特别注意:整数的除法对于除数为0时运行时将报错,但编译不会报错。

溢出

要特别注意,整数由于存在范围限制,如果计算结果超出了范围,就会产生溢出,而溢出不会出错,却会得到一个奇怪的结果:

//运算溢出
public class Main {public static void main(String[] args) {int x = 2147483640;int y = 15;int sum = x + y;System.out.println(sum); // -2147483641  ,正数相加竟然成为了负数}
}

要解释上述结果,我们把整数214748364015换成二进制做加法:

由于最高位计算结果为1,因此,加法结果变成了一个负数。

要解决上面的问题,可以把int换成long类型,由于long可表示的整型范围更大,所以结果就不会溢出:

//运算正常
public class Main {public static void main(String[] args) {long x = 2147483640;long y = 15;long sum = x + y;System.out.println(sum);   // 2147483655}
}

简洁的运算符

有一种简写的运算符,即+=-=*=/=,它们的使用方法如下:

n += 100;     // 3409, 相当于 n = n + 100;
n -= 100;    // 3309, 相当于 n = n - 100;

自增/自减

Java还提供了++运算和--运算,它们可以对一个整数进行加1和减1的操作:

// 自增/自减运算
public class Main {public static void main(String[] args) {int n = 3300;n++; // 3301, 相当于 n = n + 1;n--; // 3300, 相当于 n = n - 1;int y = 100 + (++n); // 不要这么写System.out.println(y);}
}

注意++写在前面和后面计算结果是不同的,++n表示先加1再引用n,n++表示先引用n再加1。不建议把++运算混入到常规运算中,容易自己把自己搞懵了。

移位运算

在计算机中,整数总是以二进制的形式表示。例如,int类型的整数7使用4字节表示的二进制如下:

00000000 0000000 0000000 00000111

可以对整数进行移位运算。对整数7左移1位将得到整数14,左移两位将得到整数28

int n = 7;       // 00000000 00000000 00000000 00000111 = 7
int a = n << 1;  // 00000000 00000000 00000000 00001110 = 14
int b = n << 2;  // 00000000 00000000 00000000 00011100 = 28
int c = n << 28; // 01110000 00000000 00000000 00000000 = 1879048192
int d = n << 29; // 11100000 00000000 00000000 00000000 = -536870912

左移29位时,由于最高位变成1,因此结果变成了负数。

类似的,对整数28进行右移,结果如下:

int n = 7;       // 00000000 00000000 00000000 00000111 = 7
int a = n >> 1;  // 00000000 00000000 00000000 00000011 = 3
int b = n >> 2;  // 00000000 00000000 00000000 00000001 = 1
int c = n >> 3;  // 00000000 00000000 00000000 00000000 = 0

如果对一个负数进行右移,最高位的1不动,结果仍然是一个负数:

int n = -536870912;  //11100000 00000000 00000000 00000000
int a = n >> 1;  // 11110000 00000000 00000000 00000000 = -268435456
int b = n >> 2;  // 11111000 00000000 00000000 00000000 = -134217728
int c = n >> 28; // 11111111 11111111 11111111 11111110 = -2
int d = n >> 29; // 11111111 11111111 11111111 11111111 = -1

对比了两种的移位运算之后,我客观总结一下>>(右移)使用1来填补,<<(左移)使用0来填补。
如果从数学原理来理解的话就是,左移是满2进1,原位补0。右移是减1退位,原位补1。

还有一种不带符号的右移运算,使用>>>,它的特点是符号位跟着动,因此,对一个负数进行>>>右移,它会变成正数,原因是最高位的1变成了0

int n = -536870912;// 11100000 00000000 00000000 00000000
int a = n >>> 1;  // 01110000 00000000 00000000 00000000 = 1879048192
int b = n >>> 2;  // 00111000 00000000 00000000 00000000 = 939524096
int c = n >>> 29; // 00000000 00000000 00000000 00000111 = 7
int d = n >>> 31; // 00000000 00000000 00000000 00000001 = 1

byteshort类型进行移位时,会首先转换为int再进行位移。

仔细观察可发现,左移实际上就是不断地×2,右移实际上就是不断地÷2。

位运算

位运算是按位进行与、或、非和异或的运算。

  • 与运算的规则是,必须两个数同时为1,结果才为1
n = 0 & 0; // 0
n = 0 & 1; // 0
n = 1 & 0; // 0
n = 1 & 1; // 1

  • 或运算的规则是,只要任意一个为1,结果就为1
n = 0 | 0; // 0
n = 0 | 1; // 1
n = 1 | 0; // 1
n = 1 | 1; // 1

  • 非运算的规则是,01互换:
n = ~0; // 1
n = ~1; // 0

  • 异或运算的规则是,如果两个数不同,结果为1,否则为0
n = 0 ^ 0; // 0
n = 0 ^ 1; // 1
n = 1 ^ 0; // 1
n = 1 ^ 1; // 0

对两个整数进行位运算,实际上就是按位对齐,然后依次对每一位进行运算。例如:

public class Main {public static void main(String[] args) {int i = 167776589; // 00001010 00000000 00010001 01001101int n = 167776512; // 00001010 00000000 00010001 00000000// i&n = 00001010 00000000 00010001 00000000 = 167776512System.out.println(i & n); // 167776512}
}

上述按位与运算实际上可以看作两个整数表示的IP地址10.0.17.7710.0.17.0,通过与运算,可以快速判断一个IP是否在给定的网段内。

运算优先级

在Java的计算表达式中,运算优先级从高到低依次是:

  • ()
  • ! ~ ++ --
  • * / %
  • + -
  • << >> >>>
  • &
  • |
  • += -= *= /=

记不住也没关系,只需要加括号就可以保证运算的优先级正确。

类型自动提升与强制转型

在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。例如,shortint计算,结果总是int,原因是short首先自动被转型为int

// 类型自动提升与强制转型
public class Main {public static void main(String[] args) {short s = 1234;int i = 123456;int x = s + i; // s自动转型为intshort y = s + i; // 编译错误!   因为int型一般情况下是不可以转化成为short类型的}
}

但是也还是可以将结果强制转型,即将大范围的整数转型为小范围的整数。强制转型使用(类型),例如,将int强制转型为short

int i = 12345;        //12345为int型
short s = (short) i; // 12345为short型

要注意,超出范围的强制转型会得到错误的结果,原因是转型时,int的两个高位字节直接被扔掉,仅保留了低位的两个字节。
例如:7(int)=0111(int) <------> 7(short)= 11(short)

//强制转换类型
public class Main {public static void main(String[] args) {int i1 = 1234567;short s1 = (short) i1; // -10617System.out.println(s1);int i2 = 12345678;short s2 = (short) i2; // 24910System.out.println(s2);}
}

因此,强制转型的结果很可能是错的。

小结

整数运算的结果永远是精确的;

运算结果会自动提升;

可以强制转型,但超出范围的强制转型会得到错误的结果;

应该选择合适范围的整型(intlong),没有必要为了节省内存而使用byteshort进行整数运算。

4、浮点数运算

浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算和移位运算。

在计算机中,浮点数虽然表示的范围大,但是,浮点数有个非常重要的特点,就是浮点数常常无法精确表示。

举个栗子:

浮点数0.1在计算机中就无法精确表示,因为十进制的0.1换算成二进制是一个无限循环小数,很显然,无论使用float还是double,都只能存储一个0.1的近似值。但是,0.5这个浮点数又可以精确地表示。

因为浮点数常常无法精确表示,因此,浮点数运算会产生误差:

//浮点数运算误差
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);System.out.println(y);}
}

  • 由于浮点数存在运算误差,所以比较两个浮点数是否相等常常会出现错误的结果。正确的比较方法是判断两个浮点数之差的绝对值是否小于一个很小的数:
// 比较x和y是否相等,先计算其差的绝对值:
double r = Math.abs(x - y);   //Math.abs()是求绝对值的
// 再判断绝对值是否足够小:
if (r < 0.00001) {// 可以认为相等
} else {// 不相等
}

浮点数在内存的表示方法和整数相比更加复杂。Java的浮点数完全遵循IEEE-754标准,这也是绝大多数计算机平台都支持的浮点数标准表示方法。

类型提升

如果参与运算的两个数其中一个是整型,那么整型可以自动提升到浮点型:

public class Main {public static void main(String[] args) {int n = 5;double d = 1.2 + 24.0 / n; // 6.0System.out.println(d);}
}

需要特别注意,在一个复杂的四则运算中,两个整数的运算不会出现自动提升的情况。

例如:

double d = 1.2 + 24 / 5;      // d = 5.2   【 24 / 5= 4.8(int)=4 】

计算结果为5.2,原因是编译器计算24 / 5这个子表达式时,按两个整数进行运算,结果仍为整数4

溢出

整数运算在除数为0时会报错,而浮点数运算在除数为0时,不会报错,但会返回几个特殊值:

  • NaN表示Not a Number
  • Infinity表示无穷大
  • -Infinity表示负无穷大

例如:

double d1 = 0.0 / 0; // NaN
double d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity

这三种特殊值在实际运算中很少碰到,我们只需要了解即可。

强制转型

可以将浮点数强制转型为整数。在转型时,浮点数的小数部分会被丢掉。如果转型后超过了整型能表示的最大范围,将返回整型的最大值。例如:

int n1 = (int) 12.3; // 12
int n2 = (int) 12.7; // 12
int n2 = (int) -12.7; // -12
int n3 = (int) (12.7 + 0.5); // 13
int n4 = (int) 1.2e20; // 2147483647  ,因为超过了整型能表示的最大范围,所以放回整型的最大值

注意:1.2e20 = 1.2 x 1020
如果转型后超过了整型能表示的最大范围,将返回整型的最大值。

如果要进行四舍五入,可以对浮点数加上0.5再强制转型:

// 四舍五入
public class Main {public static void main(String[] args) {double d = 2.6;int n = (int) (d + 0.5); //加上5,然后能进位的进位,不能进位的被丢弃System.out.println(n);}
}

PS:想要关注更多最新文章可以关注我的微信【苦逼的学生仔】

java负数右移_收入囊中篇---Java程序基础(二)相关推荐

  1. 视频教程-Java学习指南(Swing高级篇)-Java

    Java学习指南(Swing高级篇) 邵发,清华大学毕业,从业软件开发十余年,自2015年起致力于C/C++/Java等基础教育领域,希望能通过提高每一个个体的素质来推动中国IT业的整体发展.代表作: ...

  2. java 证件识别_证件识别接口JAVA调用示例

    此篇java文章是基本聚合数据(http://www.juhe.cn)-----证件识别接口来演示,基本HTTP POST请求上传图片并接收JSON数据来处理,其他与上传图片相关的接口请求可参考此篇文 ...

  3. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  4. java内置_自包含的应用程序,内置Java

    我已经看过几篇在Java 9中简要提到自包含应用程序的在线演示文稿,但我有一个问题需要我解决. 使用新模块系统,您现在只允许包含运行应用程序所需的最少代码.但是,希望运行应用程序的系统是否仍需要JRE ...

  5. java 判断类型_如何快速入门Java编程学习(干货)

    一.初识Java 1.生活中的程序: 从起床到教室上课的过程 穿衣打扮>起床>洗漱>出宿舍>>吃早餐>到教室 按照特定的顺序去完成某一件事的过程我们叫做生活中的程序 ...

  6. java 异常信息_优雅的异常处理 -- Java中的异常

    处理异常自己处理 try-catch抛出让别人处理 throws 获得异常信息 直接打印异常对象 通过异常对象调用getMessage()方法获得 通过异常对象调用printStackTrace()方 ...

  7. 支持java虚拟主机_为何缺乏支持Java的虚拟主机

    现在很多站长们,都青睐于香港虚拟主机建站.现在常见的是asp和PHP的程序空间很多,但是Java的少之又少,下面小编我给大家聊一聊! 一.香港Java虚拟主机成本高 使用Java程序建站,就必须要用支 ...

  8. java word批注_使用反射处理Java批注

    java word批注 在上一篇有关Java注释的文章中,我概述了一个最近的用例,并为您提供了一些自定义注释的示例以及如何使用它们. 在本文中,我将更进一步,并为您提供一些自定义注释的示例,以及如何使 ...

  9. java线程堆栈_深入JVM剖析Java的线程堆栈

    在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术.在线程堆栈中存储的信息,通常远超出你的想象 ...

最新文章

  1. inconfont 字体库应用
  2. JNI/NDK开发指南(八)——调用构造方法和父类实例方法
  3. Java GC收集器配置说明
  4. IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法...
  5. 超强 css 实现 table 隔行 ,隔列 换色
  6. Mysql在离线安装时提示:error: Found option without preceding group in config file
  7. TensorFlow学习笔记(六)Variable变量
  8. 进程 zabbix_Zabbix监控在windows的进程(非进程数)
  9. WEB安全基础-文件下载漏洞以及文件包含漏洞演示
  10. 音乐陶冶情操,怎样让孩子喜欢音乐?
  11. python image 转成字节_Python 办公自动化之 Excel(下)
  12. 图片版坦克大战其他相关的 类(三)
  13. java 反序列化 怎么知道类_理解java中的序列化与反序列化
  14. 同时安装vs2005团队开发版和sql 2005企业版
  15. 【AR优秀开源项目】ARCore项目工程汇总
  16. 向量微积分——理解梯度
  17. ImportError: Could not import
  18. 24位真彩色图片取摸方法(用于WS2812显示)
  19. libtorch opecv c++ cmake clion
  20. hbase和es在搜索场景的应用

热门文章

  1. Vue登录切换中的问题及解决
  2. TVM适配NN编译Compiler缺陷
  3. ARM CPU自动调度神经网络
  4. 激光雷达Lidar Architecture and Lidar Design(下)
  5. CUDA刷新:GPU计算生态系统
  6. 2021年大数据Spark(四十九):Structured Streaming 整合 Kafka
  7. Dockerfile的详解
  8. [JS] [编程题] 配置文件恢复
  9. java显示当月数据_Java统计当月与往月数据 使用StringTemplate
  10. Caused by: java.lang.IllegalStateException: View ' '