《从头开始学java,一天一个知识点》之:运算符与表达式:算术、比较和逻辑运算

简介: **你是否也经历过这些崩溃瞬间?**- 看了三天教程,连`i++`和`++i`的区别都说不清- 面试时被追问"`a==b`和`equals()`的区别",大脑突然空白- 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符这个系列为你打造Java「速效救心丸」,每天1分钟,地铁通勤、午休间隙即可完成学习。直击高频考点和实际开发中的「坑位」,拒绝冗长概念,每篇都有可运行的代码示例。明日预告:《控制流程:if-else条件语句实战》。

你是否也经历过这些崩溃瞬间?

  • 看了三天教程,连i++++i的区别都说不清
  • 面试时被追问"a==bequals()的区别",大脑突然空白
  • 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符

🚀 这个系列就是为你打造的Java「速效救心丸」!
我们承诺

✅ 每天1分钟:地铁通勤、午休间隙即可完成学习

✅ 直击痛点:只讲高频考点和实际开发中的「坑位」

✅ 拒绝臃肿:没有冗长概念堆砌,每篇都有可运行的代码标本

明日预告:《控制流程:if-else条件语句实战》
Snipaste_2025-03-04_09-52-03.png

一、🎞️初识运算符:代码世界的数学法则(代码实例)

// 算术运算
int result = 10 + 3 * 5; // 结果=25(不是65!)
double pi = Math.PI % 3; // 取模运算的特殊用法

// 比较运算
boolean flag = (new Integer(127) == 127); // 自动拆箱陷阱

// 逻辑运算
String user = null;
if (user != null && user.length() > 0) {
    // 短路运算避免NPE
    System.out.println("Valid user");
}

二、👓实战对比视角:跨语言运算符的暗礁

1. Java vs Python优先级差异

# Python中**优先级高于位运算
print(2 ** 3 & 1)  # 输出0 → (8) & 1
// Java中位运算符优先级混乱
System.out.println(2 * 3 & 1); // 输出0 → (6) & 1
System.out.println(8 ^ 3 << 1); // 输出22 → 8^(6)

开发警示:Java的<<优先级低于算术运算符,混合使用时建议显式加括号

🎢2. i++与++i性能实测

// JMH基准测试结果(ns/op)
@BenchmarkMode(Mode.AverageTime)
public class IncrementBenchmark {
   
    @Benchmark
    public void prefix() {
   
        for (int i = 0; i < 1_000_000; ++i) {
   }
    }

    @Benchmark
    public void postfix() {
   
        for (int i = 0; i < 1_000_000; i++) {
   }
    }
}
// 测试结果差异 <1%(现代JVM已优化)

结论:性能差异可忽略,代码可读性优先


三、🍤高频面试陷阱:你能全躲过吗?

1. 类型转换谜题

Object result = (short)1 + (byte)2; // 实际类型是int!
System.out.println(result.getClass()); // class java.lang.Integer

2. 字符串比较陷阱

String s1 = new String("Java");
String s2 = "Java";
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true

3. 三目运算符的自动拆箱

Integer a = null;
int b = true ? a : 0; // 抛出NPE

四、💂工程化思维:从代码到生产级方案

1. 防御性编程示例

public void processOrder(Order order) {
   
    // 使用短路与避免深层null检查
    if (order != null 
        && order.getUser() != null
        && order.getUser().getAddress() != null) {
   
        // 安全操作
    }
}

2. 金额计算工具类

public class MoneyUtil {
   
    // 使用分作为基本单位避免浮点误差
    public static int add(int centsA, int centsB) {
   
        return centsA + centsB;
    }

    public static String format(int cents) {
   
        return cents / 100 + "." + cents % 100;
    }
}

五、🫠可视化记忆:让知识刻进DNA

1. 运算符优先级口诀

单算移关与,异或逻条赋
(谐音:单身算一关,鱼饵逻辑调副)
解释:单目→算术→移位→关系→按位与→异或→按位或→逻辑与→逻辑或→三目→赋值

2. 逻辑运算ASCII流程图

   a > b?
  /      \
true    false
 |        |
c != d?  整个表达式=false
/     \
true  false
 |      |
整个   整个
表达式=true 表达式=false

六、⚓深度解析:运算符背后的计算机科学原理

一、JVM视角下的运算符执行机制

1. 类型提升的字节码证据

byte a = 10;
short b = 20;
int c = a + b; // 查看字节码:
iload_1    // 加载byte类型变量(实际转为int)
iload_2    // 加载short类型变量(转为int)
iadd       // 执行int相加
istore_3   // 存储结果

本质揭示:JVM运算最小单位是int类型,所有小于int的类型运算都会发生隐式类型转换

2. 逻辑运算符的短路实现

if (a() && b()) {
    ... }

对应字节码:

invokestatic a()Z
ifeq falseLabel // 如果a()为false直接跳转
invokestatic b()Z
ifeq falseLabel

二、编译器优化黑魔法

1. 常量折叠优化

int x = 10 + 20 * 3; 
// 编译后直接变为:
int x = 70;

2. 循环中的前缀/后缀优化

现代编译器会将:

for (int i=0; i<100; i++) {
   }

优化为:

for (int i=0; i<100; ++i) {
   }

三、运算符在算法中的妙用

1. 快速判断2的幂次

boolean isPowerOfTwo = (n & (n - 1)) == 0;

2. 不用临时变量交换数值

a ^= b;
b ^= a;
a ^= b;

3. RGB颜色解码器

int rgb = 0xFF0099;
int red = (rgb >> 16) & 0xFF;   // 0xFF
int green = (rgb >> 8) & 0xFF;  // 0x00
int blue = rgb & 0xFF;          // 0x99

4.布隆过滤器位操作

// 使用位运算快速定位多个哈希位置
long[] bits = new long[1024];
int hash1 = ...;
int hash2 = ...;
bits[hash1 >> 6] |= (1L << (hash1 & 0x3F));
bits[hash2 >> 6] |= (1L << (hash2 & 0x3F));

七、🤔字节码视角:揭开运算符的底层面纱

1. 自增运算的指令差异

// 原始代码
void demo() {
   
    int i = 0;
    i++;
    ++i;
}

// javap -c 反编译结果
0: iconst_0
1: istore_1
2: iinc        1, 1  // i++ 直接修改局部变量表
5: iinc        1, 1  // ++i 同样优化为iinc指令

洞见:现代JVM已优化前缀/后缀自增的底层实现,性能差异更多存在于理论层面


八、🌅热点场景:框架中的运算符艺术

1. Spring条件注解的运算符运用

    @Configuration
    @ConditionalOnExpression(
        "#{T(java.lang.Math).random() > 0.5} " +
        "&& '${server.env}' == 'prod'"
    )
    public class RiskControlConfig {
   
        // 动态启用配置
    }

2. MyBatis动态SQL中的比较陷阱

    <if test="age != null and age > 18">
       AND status = 'ADULT'
    </if>
    <!-- 必须同时判空与比较,避免NPE -->

九、❤️调试技巧:运算符引发的诡异Bug

1. 浮点数精度幽灵

    // 错误现象
    System.out.println(0.1 + 0.2 == 0.3); // false

    // 调试方案
    BigDecimal a = new BigDecimal("0.1");
    BigDecimal b = new BigDecimal("0.2");
    System.out.println(a.add(b).equals(new BigDecimal("0.3"))); // true

2. 三目运算符类型推导

    // 编译错误示例
    Object o = true ? "hello" : 123; 
    // 实际类型是Serializable接口类型!

十、👮工具武装:让IDE成为你的侦察兵

1. IDEA运算符检测配置

  1. 开启悬浮提示:显示运算符优先级
  2. 启用自动括号补全(Preferences → Editor → General → Smart Keys)
  3. 配置代码检查规则:检测可能的位运算错误

十一、🧁安全红线和最佳实践

禁止清单

🚫 在商业计算中使用float/double\
🚫 在复杂表达式中混合使用不同类运算符\
🚫 在循环条件中使用带有副作用的表达式

推荐模式

✅ 金额计算统一使用BigDecimal或分存储\
✅ 多运算符表达式显式使用括号\
✅ 逻辑判断前进行防御性空检查


十二、🎗️自我检验:你的Java运算符段位

青铜级

  • 能正确使用基本算术运算符
  • 理解==和equals的区别

王者级

  • 能解释自动装箱拆箱对运算符的影响
  • 会使用位运算优化权限控制系统
  • 能诊断运算符优先级引发的生产事故

    // 终极挑战:预测输出结果
    public class OperatorQuiz {
   
        public static void main(String[] args) {
   
            int x = 5;
            x += x++ * ++x / x--;
            System.out.println(x); // 答案见文末
        }
    }

(答案:通过反编译分析可得最终结果,此处暂不揭晓以鼓励读者实践)

Suggestion.gif

目录
相关文章
|
30天前
|
存储 Java
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
39 12
|
18天前
|
缓存 监控 Java
深入解析java正则表达式
本文深入解析Java正则表达式的应用,从基础概念到实际开发技巧全面展开。正则表达式是一种强大的文本处理工具,广泛应用于格式验证、搜索替换等场景。Java通过`Pattern`和`Matcher`类支持正则表达式,`Pattern.compile()`方法将正则字符串编译为高效模式对象。文章详细介绍了核心类的功能、常用正则语法及实际案例(如邮箱和电话号码验证)。掌握这些内容,可显著提升文本处理能力,满足多种开发需求。
49 1
|
18天前
|
Java 编译器 API
Java Lambda 表达式:以 Foo 接口为例深入解析
本文深入解析了 Java 8 中 Lambda 表达式的用法及其背后的函数式接口原理,以 `Foo` 接口为例,展示了如何通过简洁的 Lambda 表达式替代传统匿名类实现。文章从 Lambda 基本语法、函数式接口定义到实际应用层层递进,并探讨默认方法与静态方法的扩展性,最后总结常见误区与关键点,助你高效优化代码!
39 0
|
1月前
|
SQL Rust Java
怎么理解Java中的lambda表达式
Lambda表达式是JDK8引入的新语法,用于简化匿名内部类的代码写法。其格式为`(参数列表) -&gt; { 方法体 }`,适用于函数式接口(仅含一个抽象方法的接口)。通过Lambda表达式,代码更简洁灵活,提升Java的表达能力。
|
2月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
213 60
【Java并发】【线程池】带你从0-1入门线程池
|
20天前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
56 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
|
1月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
99 23
|
26天前
|
数据采集 存储 网络协议
Java HttpClient 多线程爬虫优化方案
Java HttpClient 多线程爬虫优化方案
|
1月前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
158 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
下一篇
oss创建bucket