[Java解惑]读书笔记分享

news2025/1/11 19:46:35

[Java解惑]读书笔记分享
这本书主要讲了Java中经常遇到的坑, 并给出了解释以及解决办法. 读完之后很有收获
在这里插入图片描述

  • 读书笔记
    • 表达式之谜

      • 奇数性

        用下面的表达式判断一个数是否是奇数

        public static boolean isOdd(int i) {
              return i % 2 == 1;
          }
        

        问题: 负数无法得出正确的结果. 例如当 i = -3时, 上述结果是-1.

        可以修改为如下形式

        public static boolean isOdd(int i) {
              return i % 2 != 0;
          }
        

        更进一步的, 可以考虑把区域操作改为AND(&).

        public static boolean isOdd(int i) {
              return (i & 1) != 0;
          }
        
      • 找0时刻

        计算表达式

        System.out.println(2.00 - 1.10);
        // 0.8999999999999999
        

        原因: 并非所有的小数都可以用二进制浮点数明确表示

        请注意, 虽然表达式System.*out*.printf("%.2f", (2.00 - 1.10));会显示出正确的结果, 但是这并不表示是对底层通用的解决方案.

        因为二进制浮点数对于货币运算是非常不合适的.

        一种方案是以分为单位, 另外一种是使用BigDecimal.

        BigDecimal bigDecimalA = new BigDecimal("2.0");
        BigDecimal bigDecimalB = new BigDecimal("1.1");
        System.out.println(bigDecimalA.min(bigDecimalB));
        

        一定要使用字符串构造参数BigDecima(String), 不要使用BigDecima(double).

        BigDecimal bigDecimal = new BigDecimal(.1);
        System.out.println(bigDecimal);
        // 0.1000000000000000055511151231257827021181583404541015625
        
      • 长整除

        两个long类型的数相除.

        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
        

        运行结果是5

        MICROS_PER_DAY溢出了. 虽然放在long中是可以的, 但是放在int中会溢出.

        这个计算是按照int来计算的, 只有在运算完之后, 才会被提升到long, 而此时已经溢出了.

        为什么会按照int的方式计算? 因为所有的因子都是int类型.

        一种比较好的方式是把long类型作为第一个因子.

        修改后的程序如下

        final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
        
      • 初级问题

        计算表达式

        System.out.println(12345 + 5432l);
        // 17777
        

        为什么会这样呢?

        5432l中的l, 表示该数字是long类型. 因此建议写成大写.

      • 十六进制的趣事

        计算下面表达式

        System.out.println(Long.toHexString(0x100000000L + 0xcafebabe));
        // cafebabe
        

        为什么不是1cafebabe

        要注意到, 十六进制不像十进制一样字面量都是正的, 如果想表示负数在前面加-号就可以了.

        System.out.println(0xcafebabe); // -889275714
        System.out.println(0x1cafebabeL); // 7700658878
        

        因此, 该表达式左侧是一个long类型数字, 右侧是一个int类型的数字, 且为负数. 为了执行该运算, 会将int类型转化为long类型. 提升之后的数字是0xffffffffcafebabe.

        修改方法如下. 即把两个数字都变成long类型.

        System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));
        
      • 多重转型

        观察下面表达式

        System.out.println((int)(char)(byte)-1);
        

        其结果不是-1, 而是65535

        转化顺序是 int → byte → char → int

        该程序的行为紧密依赖于转型的符号扩展行为. Java使用基于2的补码的二进制运算, 因此int类型的数值-1的所有32位都是置位的.

        第一次从int → byte, 窄化转换, 仍是-1.

        第二次byte → char, 拓展并窄化的转化. byte是有符号类型的, char是无符号类型的. 不能用char表示一个负的byte. 因此这个过程是byte → int → char.

        可以将规则描述如下: 如果最初的数值类型是有符号的,那么就执行符号扩展。如果他是char那么不管他将要被转化成什么类型,都执行零扩展。

      • 互换内容

        int x = 1984;
        int y = 2001;
        x^= y^= x^= y;
        System.out.println("x = " + x + " y = " + y);
        // x = 0 y = 1984
        

        一种可行的方式如下

        int x = 1984;
        int y = 2001;
        x = x ^ y;
        y = y ^ x;
        x = x ^ y;
        System.out.println("x = " + x + " y = " + y);
        // x = 2001 y = 1984
        

        这种方式不推荐使用.

        Java的操作符操作是从左到右执行的.

        给我们的经验就是不要对相同的变量赋值两次.

      • Dos Equis

        观察下面表达式

        char x = 'X';
        int i = 0;
        System.out.println(true ? x : 0);
        System.out.println(false ? i : x);
        // X
        // 88
        

        转化规则如下

        最好在条件表达式中使用相同的类型.

      • 半斤

        不能简单的认为下面两个表达式是相等的

        x += i;
        x = x + 1;
        

        原因如下

        可以观察下面的例子

        short x = 0;
        int i = 123456;
        x += i;
        System.out.println(x);
        // -7616
        

        因此, 不要将符合运算符用于byte, short, char类型. 避免符合类型的转型.

      • 八两

        但是, 上面的例子反过来, 也不能就认为高枕无忧了.

        复合赋值操作符要求两个操作数都是原生类型的,例如int。或包装了的原生类型。例如integer. 但是有一个例外, 那就是如果操作符左侧的操作数是string类型的。那么他允许右侧的操作数是任意类型。

    • 字符之谜

      • 最后的笑声
      • ABC
      • 动物庄园
      • 转义字符的溃败
      • 令人晕头转向的Hello
      • 行打印程序
      • 嗯?
      • 字符串奶酪
      • 漂亮的火花
      • 我的类是什么
      • 我的类是什么? 镜头2
      • URL的愚弄
      • 不劳无获
    • 循环之谜

    • 异常之迷

    • 类之迷

    • 库之迷

    • 更多类之谜

    • 更多库之迷

    • 高级谜题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379856.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

建模杂谈系列210 人工智能培训内容梳理

说明 最近打算做一次针对银行的人工智能培训,这里梳理一下培训内容的大纲。以前做过一次很细致的培训,但是现在感觉当时很多文档和内容整理的还是不够方便。 借此机会把这些内容整理好,分门别类放好,争取再有一下次培训的时候可…

嵌入式开发:实时系统中的嵌入式数据库

“实时”这个术语是数据库系统供应商随便说说的,但是实时在嵌入式系统中一直有特定的含义。“实时系统意味着系统是实时的,换句话说,响应应该在指定的时间限制内得到保证,或者系统应该满足指定的期限。例如,飞行控制系…

单目标应用:蜣螂优化算法DBO优化RBF神经网络实现数据预测(提供MATLAB代码)

一、RBF神经网络 1988年,Broomhead和Lowc根据生物神经元具有局部响应这一特点,将RBF引入神经网络设计中,产生了RBF(Radical Basis Function)。1989年,Jackson论证了RBF神经网络对非线性连续函数的一致逼近性能。 RBF的基本思想是…

【面试题】对async/await 的了解?

前言大厂面试题分享 面试题库后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库“编程,就像一场开卷考试,题目的答案取决于对书本内容的熟悉程度;而一份源代码就好比一本书&#xff0c…

源码才十几行的数组转换工具arrify,快学起来

前言 前几天在项目中运用到了arrify工具,今天便阅读了arrify的源码,整个源码部分不过才十几行,而且也不难,所以来分享一下阅读心得。 arrify介绍 arrify是什么,有什么作用,或许有些小伙伴还不清楚。简单…

web测试的基本流程

1、web测试流程: (1)web测试 1)参与一个web新项目的测试前,先搜集测试相关的资料,包括原型图、各种需求文档、业务相关等需求相关材料 2)结合第一步搜集到的需求相关资料,自行熟悉系统,同时列出不明白的点,…

时间API在更新,传奇已经谢幕,但技术永远不死

(Bill Joy(左一),Vinod Khosla(左二),Andy Bechtolsheim(右二),Scott McNealy(右一) ) CSDN 博文征集活动(和日期相关的代码和bug):点击这里 各位 “big guys”,这篇博文…

植物大战 二叉搜索树——C++

这里是目录标题二叉排序树的概念模拟二叉搜索树定义节点类insert非递归Finderase(重点)析构函数拷贝构造(深拷贝)赋值构造递归FindRInsertR二叉搜索树的应用k模型KV模型二叉排序树的概念 单纯的二叉树存储数据没有太大的作用。 搜索二叉树作用很大。 搜索二叉树的一般都是用…

摸鱼用python获取弹幕的两种方式【前者简单,后者数据好看】

嗨害大家好鸭!我是小熊猫~ 相信大家对于 “弹幕文化” 已经相当熟悉啦 你不是一个人在看——这就是弹幕网站的存在感。 它形成了新的“抱团”观看模式, 也真正实现了无时空距离的社交。 有网友表示,弹幕简直比剧情还有趣。 看似简单的寥寥…

【ES】Elasticsearch-深入理解索引原理

文章目录Elasticsearch-深入理解索引原理读操作更新操作SHARD不变性动态更新索引删除和更新实时索引更新持久化Segment合并近实时搜索,段数据刷新,数据可见性更新和事务日志更新索引并且将改动提交修改Searcher对象默认的更新时间Elasticsearch-深入理解…

CentOS8基础篇9:进程的延迟与周期调度

一、进程的概念 进程:开始执行但是还没有结束的程序的实例 程序:包含可执行代码的文件 进程与程序的关系 进程由程序产生,是一个运行着的、要占系统资源的程序 进程不等于程序 浏览网络时,打开多个IE浏览器程序;…

一文讲清楚如何进行主数据编码

主数据编码作为一类重要的数据资源,在信息化建设中具有重要的地位和作用,是保证现有信息系统和未来新系统建设成功的关键因素,决定着系统中的信息一致性。 编码,是一件简单的事情,但绝对不是一件容易做好的事情&#…

FPGA案例开发手册——基于全志T3+Logos FPGA核心板

前 言 本文档主要提供评估板FPGA端案例测试方法,适用的开发环境为Windows 7 64bit和Windows 10 64bit。 本文案例基于创龙科技的全志T3+Logos FPGA核心板,它是一款基于全志科技T3四核ARM Cortex-A7处理器 + 紫光同创Logos PGL25G/PGL50G FPGA设计的异构多核全国产工业核心板…

PImpl(Pointer to Implementation)指向实现的指针 [使用ChatGPT学习系列]

PImpl是Pointer to Implementation的缩写,也被称为“编译期实现”,是一种C设计的模式。 用于将类的实现细节与其公共接口分离开来。该模式的核心思想是 通过一个指向类的实现的指针来隐藏类的实现细节,从而提高类的封装性和安全性。PImpl是一…

「考研算法」

考研算法 前言 本系列文章涉及的算法内容,针对的是哈尔滨工业大学854科目。在本文中通过具体的算法题进行讲解相应算法。 今天涉及的算法主要有线性筛,十大排序中快速排序和归并排序。 后续会有动态规划的相关算法以及尝试模型的总结,如果…

[Java·算法·中等]LeetCode17. 电话号码的字母组合

每天一题,防止痴呆题目示例分析思路1题解1分析思路2题解2题目 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。…

本科毕业设计-基于ORB SLAM3的多从机SLAM导航系统

耗时:两个月 需求:多从机协作 多地图系统 稠密建图 定位 导航 硬件:二个D435 一台X86主机(CPU:13600kf 内存:32G) X86主机环境:ubuntu18.04 opencv3.2 ROS1 主要代码参考:ORB-SLAM3 主要调用…

【CNN】FractalNet——与DenseNet有异曲同工之妙

FractalNet论文名称:FractalNet: Ultra-Deep Neural Networks without Residuals FractalNet论文下载链接: FractalNet(分型网络),2016年Gustav Larsson首次提出。 (1)分形网络不像resNet那样…

嵌入式 Linux 文件IO操作

目录 Linux 文件操作 1 Linux 系统环境文件操作概念 2 缓冲 IO 文件操作 1 文件的创建,打开与关闭 fopen 函数函数 2 freopen 函数 3、fdopen函数 4、fclose函数 5、格式化读写 6、单个字符读写 7、文件定位 8、标准目录文件 9、非缓冲IO文件操作 Linux 文…

十二、MyBatis的高级映射及延迟加载

1 数据库表的准备 准备数据库表:一个班级对应多个学生。班级表:t_clazz。学生表:t_stu 2 环境搭建 创建模块 打包方式:jar 引入依赖:mybatis依赖、mysql驱动依赖、junit依赖、logback依赖 配置文件:…