【西行 - 官封弼马温】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 零基础:彻底掌握 for 循环,打造高效程序设计
【10月更文挑战第15天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
127 63
|
29天前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
26 3
|
2月前
|
存储 算法 Java
🚀Java零基础-顺序结构详解 🚀
【10月更文挑战第11天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
39 6
|
2月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
60 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
4月前
|
Java
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
Java应用结构规范问题之在UnitConvertUtils工具类将千米转换为米的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
4月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之dal层中的mapper数据源类型进行组织的问题如何解决
Java应用结构规范问题之dal层中的mapper数据源类型进行组织的问题如何解决
|
4月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
77 0