【西行 - 官封弼马温】Java 基本程序设计结构(二)

简介: 【西行 - 官封弼马温】Java 基本程序设计结构


6、Java 运算符


运算符是一种特殊的符号,用于表示数据的运算、赋值和比较等。


Java 语言使用功能运算符讲一个或多个操作数链接成直线性语句,用于实现特定功能。


Java 语言中运算符分为如下几种:


  • 算术运算符
  • 赋值运算符
  • 比较运算符
  • 位运算符
  • 类型相关运算符(比较、逻辑、三目)


6.1 算术运算符

Java 支持所有的基本算术运算符,这些算术运算符用于执行基本的数学运算:加、减、乘、除和求余等。


下面来看看 7 个基本算术运算符。


+:加法运算符。

double a = 5.0;
double b = 3.8;
double sum = a + b;
// sum = 8.8
System.out.println(sum);


除此之外,+ 还可以作为字符串的连接运算符。


-:减法运算符。

double a = 5.0;
double b = 3.8;
double sub = a - b;
// sub = 1.2
System.out.println(sub);


*:乘法运算符。

double a = 5.0;
double b = 4.0;
double m = a * b;
// m = 20.0
System.out.println(m);


/:除法运算符。


当运算符操作的两个数都是整数类型,计算结果为整数(截取整数部分);如果运算符操作的两个数中有一个或者两个都是浮点数,计算结果则就是自然运算出来的结果,不会截取掉小数部分。

public class OperatorTest {
    public static void main(String[] args) {
        int a = 3;
        int b = 2;
        // 1
        System.out.println(a / b);
        double d = 9.5;
        int c = 3;
        // 3.1666666666666665
        System.out.println(d / c);
        // 正无穷大
        System.out.println(5 / 0.0);
        // 负无穷大
        System.out.println(-5 / 0.0);
        // 错误:/ byte zero
        System.out.println(5 / 0);
    }
}


%:求余运算符。

求余运算符的计算结果是第一个操作数除以第二个操作数,得到一个整除的结果后剩下的值就是余数,它的结果也不总是整数。


public class OperatorTest {
    public static void main(String[] args) {
        int a = 5;
        int b = 2;
        // 整数 1(余数)
        System.out.println(a % b);
        double c = 2.0;
        // 浮点数 1.0
        System.out.println(a % c);
        // 输出非数:NaN
        System.out.println(5.0 % 0);
        System.out.println(5 % 0.0);
        System.out.println(0 % 0.0);
        // 0.0
        System.out.println(0 % 5.0);
        // 报错:/ by zero
        System.out.println(5 % 0);
    }
}


++:自加。

这是单目运算符,运算符既可以出现在操作数的左边,也可以出现在操作数的右边。

左边相当于,先给数字 + 1 然后再运算;右边相当于,先运算,然后再 + 1。


int a = 3;
int b = 5;
int c = a++ + b;
// c = 8,a++ + b 相当于 c = a + b ; a = a + 1
System.out.println(c);
// a = 4
System.out.println(a);
a = 3;
int d = ++a + b;
// d = 9, ++a + b 相当于 a = a + 1 ; c = a + b;
System.out.println(d);
// a = 4
System.out.println(a);


–:自减。

和 ++ 一样也是单目运算符,是不是不是 + 1 而是 -1。


6.2 赋值运算符

赋值运算符用于为变量制定变量值,上面的所有代码都是用 = 进行赋值。

除了上面的赋值操作外,Java 赋值运算符还支持如下操作。

int f = a = b = c = d;


虽然 Java 支持这种一次为多个变量赋值的写法,但可读性不好,不建议这样做。


6.3 位运算符

Java 支持的位运算符有如下 7 个。


(&):按位与。

(|):按位或。

(~):按位非。

(^):按位异或。

(<<):左移运算符。

(>>):右移运算符。

(>>>):无符号右移运算符。


按位与、按位或、按位异或运算法则如下:

第一个运算符 第而个运算符 按位与 按位或 按位异或
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0


按位非只需要一个操作数,这个运算符将把操作数在计算机底层的二进制码按位取反。

看如下代码。


// 16
System.out.println( 88 & 21);
// 7
System.out.println( 4 | 3);


88 的二进制码是 000000000000000000000001011000 而 21 的二进制码是 000000000000000000000000000010101 运算方式如图。


image.png


左移运算符是将运算符的二进制码整体左移指定位数,左移后右边空出来的位以 0 填充,示例如下。

// 352
System.out.println( 88 << 2);


运算图。


image.png


计算左移右移还可以使用如下方式:


左乘、右移

意思是左移几位就操作数乘于 2 的几次方、反之就除于 2 的几次方。例如,88 << 2 = 88 * 2 ^ 2 = 88 * 4 = 352、8 >> 2 = 8 / 2 ^ 2 = 8 / 4 = 2。


位移运算符并不适合所有的数值类型,他们只适合对 byte 、short 、char 、int 和 long 等整数类型进行运算。除此之外,进行位移运算时还需要遵循如下规则。


对于低于 int 类型(byte、short 和 char )的操作数总是先自动类型转换为 int 类型后再移位。

对于 int 类型的整数移位 a >> b,当 b >> 32 时,系统先用 b 对 32 求余(因为 int 类型只有 32 位),得到的结果才是真正移位的位数。例如,a >> 33 和 a >> 1 的结果完全一样,而 a >> 32 的结果和 a 相同。

对于 long 类型的整数移位 a >> b,当 b > 64 时,总是先用 b 对 64 求余(因为 long 类型是 64 位),得到的结果才是真正移位的位数。


6.4 比较运算符

比较运算符用于判断两个变量或常量的大小,比较的结果是一个布尔值(true 或 false)。


Java 支持的比较运算符如下:


大于( > ):只支持左右两边操作数是数字类型,如果前面变量的值大于后面,返回 true。


大于等于( >= ):只支持左右两边操作数是数字类型,如果前面变量的值大于等于后面,返回 true。


小于( < ):只支持左右两边操作数是数字类型,如果前面变量的值小于后面,返回 true。


小于等于( <= ):只支持左右两边操作数是数字类型,如果前面变量的值小于等于后面,返回 true。


等于( == ):如果比较的两个操作数都是数值类型,即使它们的数据类型不相同,只要它们的值相等,也都返回 true 。例如 97 == ‘a’ 返回 true,5.0 == 5 也返回 true。如果两个操作数比较的是引用类型,那么只有当两个引用变量引用相同的实例时才可以比较,而且这两个引用必须指向同一个对象才会返回 true。


不等于( != ):如果比较的两个操作数都是数值类型,无论他们的数据类型是否相同,只要他们的值不相等,也都返回 true。如果两个操作数都是引用类型,只有当两个引用变量引用相同的类型实例时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。


public class CompareTest {
    public static void main(String[] args) {
        // true
        System.out.println("5.0 是否大于 4.5:" + (5.0 > 4.5));
        // true
        System.out.println("5.0 是否等于 5:" + (5.0 == 5));
        // true
        System.out.println("97 是否等于 A:" + (97 == 'a'));
        // false
        System.out.println("true 是否等于 false:" + (true == false));
        CompareTest c1 = new CompareTest();
        CompareTest c2 = new CompareTest();
        // false
        System.out.println("c1 是否等于 c2:" + (c1 == c2));
        CompareTest c3 = c1;
        // true
        System.out.println("c3 是否等于 c1:" + (c1 == c3));
    }
}


6.5 逻辑运算符

逻辑运算符用于操作两个布尔类型的变量或者常量,逻辑运算符主要有如下 6 个。


  • 与( $$ ):前后两个操作数必须都是 true 才返回 true,否则返回 false。
  • 不短路与( & ):和 && 作用相同,但不会发生短路。
  • 或( || ):只要两个数中有一个是 true,就可以返回 true,否则返回 false。
  • 不短路或( | ):和 || 作用相同,但不会发生短路。
  • 非( ! ):只需要一个操作数,如果操作数为 true ,则返回 false;如果操作数为 false,则返回 true。
  • 异或( ^ ):当两个操作数不同是才返回 true,如果两个操作数相同则返回 false。


public class LogicTest {
    public static void main(String[] args) {
        int a = 5;
        int b = 11;
        // false
        System.out.println((a == b && a == 4));
        // false,发生短路
        System.out.println((a == b && a-- == 4));
        // a = 5
        System.out.println(a);
        // false,没有发生短路
        System.out.println((b == 11 && a-- == 6));
        // a = 4
        System.out.println(a);
        a = 5;
        b = 11;
        // false 不发生短路
        System.out.println((a == b & a-- == 4));
        // 4
        System.out.println(a);
        // false
        System.out.println(!true);
    }
}


短路分两种情况。


&& 短路,当运算符左边的操作数是 false 时,发生短路,不会执行右边的判断逻辑。

|| 短路,当运算符左边操作数是 true 是,发生短路,不会执行右边的判断逻辑。


6.6 三目运算符

三目运算符只有一个:?,格式如下


表达式 ?结果1 : 结果2


如果表达式为 true 则结果就是结果1,反之就是结果2,代码如下。

int a = 4;
// a 不等于 5
System.out.println(a == 5 ? "a 等于 5" : "a 不等于 5");


6.7 运算符的结合性和优先级

Java 语言中大部分运算符只从左向右结合的,只有单目运算符、赋值运算符和三目运算符例外,其中,单目运算符、赋值运算符和三目运算符是从右向左结合的,也就是从右向左运算。


乘法和加法是两个可结合的运算,也就是说,这两个运算符左右两边的操作数可以互换位置而不会影响结果。


运算符有不同的优先级,即在表达式中的运算顺序。


运算符优先级如下表,优先级由上到下递减。


image.png

根据表中的优先级,我们分析一段代码。

int a = 4;
int b = a + 2 * a;


程序先执行 2 * a 的到 6,在执行 a + 6 得到 9。


当然上面的程序是非常简单的,但是有些面试题难度可不止这点,例如:

int a = 5;
int b = 4;
int c = a++ - --b * ++a / b-- >> 2 % a--;
// -1
System.out.println(c);


c 的值是多少?


看到这样的语句幸好是只出现在面试题中,要是谁代码中这样写,那我就要抓毛了。


因此,编写表达式时:


不要把一个表达式写的过于复杂,如果表达式过于发杂,那先分成几步来完成

不要过多的依赖运算符的优先级来控制表达式的执行顺序,可读性非常差,尽量使用()来控制执行顺序。


好了,今天的内容到这里就结束了,关注我,我们下期见

目录
相关文章
|
2月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
|
6月前
|
人工智能 JSON Java
列表结构与树结构转换分析与工具类封装(java版)
本文介绍了将线性列表转换为树形结构的实现方法及工具类封装。核心思路是先获取所有根节点,将其余节点作为子节点,通过递归构建每个根节点的子节点。关键在于节点需包含 `id`、`parentId` 和 `children` 三个属性。文中提供了两种封装方式:一是基于基类 `BaseTree` 的通用工具类,二是使用函数式接口实现更灵活的方式。推荐使用后者,因其避免了继承限制,更具扩展性。代码示例中使用了 Jackson 库进行 JSON 格式化输出,便于结果展示。最后总结指出,理解原理是进一步优化和封装的基础。
193 0
|
6月前
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
6月前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
246 5
|
10月前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
119 3
|
11月前
|
Java 测试技术 开发者
💡Java 零基础:彻底掌握 for 循环,打造高效程序设计
【10月更文挑战第15天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
327 63
|
11月前
|
存储 算法 Java
🚀Java零基础-顺序结构详解 🚀
【10月更文挑战第11天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
131 6
|
11月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
222 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
260 0
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
159 8