百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

《Java编程思想》第五版:第四章 运算符

xsobi 2024-11-23 10:51 13 浏览

Think in Java (5th)On Java 8 系列:
第5版Java编程思想,基于java8,由于第4版是基于java5,中间有很多变化,作者 [美] Bruce Eckel 更新了这一java入()quan)门(tui)指南,本书只有电子版,可在github上找到中文翻译版:https://github.com/LingCoder/OnJava8


这里只记录平时用的较少、比较冷门的知识点、或者非常非常重要的知识点做记录。



Java 是从 C++ 的基础上做了一些改进和简化发展而成的。

几乎所有运算符都只能操作基本类型(Primitives)。唯一的例外是 ===!=,它们能操作所有对象(这也是令人混淆的一个地方)。除此以外,String 类支持 ++=

赋值

基本类型的赋值都是直接的,而不像对象,赋予的只是其内存的引用。

a = b ,如果 b 是基本类型,那么赋值操作会将 b 的值复制一份给变量 a, 此后若 a 的值发生改变是不会影响到 b 的。

如果是为对象赋值,当对一个对象进行操作时,我们实际上操作的是它的引用。所以我们将右边的对象赋予给左边时,赋予的只是该对象的引用。此时,两者指向的堆中的对象还是同一个。 改变a 也就改变了 b。这是因为 a 和 b 此时指向的是堆中同一个对象。(a 原始对象的引用在 b 赋值给其时丢失,它引用的对象会在垃圾回收时被清理),这种现象通常称为别名(aliasing)

但是假若你不想出现这里的别名引起混淆的话,你可以

Bash
a.name = b.name;

这样做保留了两个单独的对象, 而不是丢弃一个并将 a 和 b 绑定到同一个对象。

方法传参:当你将引用传递给方法时,它仍指向同一对象。

Bash
a = b = c = 1;


算术运算符 包括加号 +、减号 -、除号 /、乘号 * 以及取模 %(从整数除法中获得余数)。整数除法会直接砍掉小数,而不是进位。

一元减号可以得到数据的负值。一元加号的作用相反,不过它唯一能影响的就是把较小的数值类型自动转换为 int 类型。

递增和递减

递增 ++ 和递减 --,意为“增加或减少一个单位。

“前递增”表示 ++ 运算符位于变量或表达式的前面;而“后递增”表示 ++ 运算符位于变量的后面, 递减同理。前缀时会先执行递增/减运算,再返回值。后缀时会先返回值,再执行递增/减运算。

前递增就是先加,后递增就是后加

关系运算符

关系运算符包括小于 <,大于 >,小于或等于 <=,大于或等于 >=,等于 == 和不等于 !=

==!= 比较的是对象引用

// operators/Equivalence.java
public class Equivalence {
   public static void main(String[] args) {
       Integer n1 = 47;
       Integer n2 = 47;
       System.out.println(n1 == n2);
       System.out.println(n1 != n2);
  }
}
//sout: true / false

因为 Integer 内部维护着一个 IntegerCache 的缓存,默认缓存范围是 [-128, 127],所以 [-128, 127] 之间的值用 == 和 != 比较也能能到正确的结果

如果47换成128,那么就会输出 false/true

实际使用时要用覆写后的 equals()方法进行比较 :equals() 的默认行为是比较对象的引用而非具体内容。因此,除非你在新类中覆写 equals() 方法,否则我们将获取不到想要的结果。好在大多数 Java 库类通过覆写 equals() 方法比较对象的内容而不是其引用。

逻辑运算符

每个逻辑运算符 &&AND)、||OR)和 !)根据参数的逻辑关系生成布尔值 truefalse

但是 请注意,如果在预期为 String 类型的位置使用 boolean 类型的值,则结果会自动转为适当的文本格式(即 "true" 或 "false" 字符串)。

逻辑运算符支持一种称为“短路”(short-circuiting)的现象。整个表达式会在运算到可以明确结果时就停止并返回结果,这意味着该逻辑表达式的后半部分不会被执行到。

字面常量值

通常,当我们向程序中插入一个字面值常量(Literal)时,编译器会确切地识别它的类型。当类型不明确时,必须辅以字面值常量关联来帮助编译器识别。

在文本值的后面添加字符可以让编译器识别该文本值的类型。对于 Long 型数值,结尾使用大写 L 或小写 l 皆可(不推荐使用 l,因为容易与阿拉伯数值 1 混淆)。大写 F 或小写 f 表示 float 浮点数。大写 D 或小写 d 表示 double 双精度。

       int i1 = 0x2f; // 16进制 (小写)
       int i2 = 0X2F; // 16进制 (大写)
       int i3 = 0177; // 8进制 (前导0)
       char c = 0xffff; // 最大 char 型16进制值
       byte b = 0x7f; // 最大 byte 型16进制值 01111111;
       short s = 0x7fff; // 最大 short 型16进制值
       long n1 = 200L; // long 型后缀
       long n2 = 200l; // long 型后缀 (容易与数值1混淆)
       long n3 = 200;
       byte blb = (byte)0b00110101;
       short bls = (short)0B0010111110101111;
       int bli = 0b00101111101011111010111110101111;
       long bll = 0b00101111101011111010111110101111;
       float f1 = 1;
       float f2 = 1F; // float 型后缀
       float f3 = 1f; // float 型后缀
       double d1 = 1d; // double 型后缀
       double d2 = 1D; // double 型后缀

十六进制(以 16 为基数),适用于所有整型数据类型,由前导 0x0X 表示,后跟 0-9 或 a-f (大写或小写)。

八进制(以 8 为基数)由 0~7 之间的数字和前导零 0 表示。

Java 7 引入了二进制的字面值常量,由前导 0b0B 表示,它可以初始化所有的整数类型。

下划线

Java 7 中有一个深思熟虑的补充:我们可以在数字字面量中包含下划线 _,以使结果更清晰。这对于大数值的分组特别有用。代码示例:

double d = 341_435_936.445_667;
       System.out.println(d);
       int bin = 0b0010_1111_1010_1111_1010_1111_1010_1111;
       System.out.println(Integer.toBinaryString(bin));
       System.out.printf("%x%n", bin); // [1]
       long hex = 0x7f_e9_b7_aa;
       System.out.printf("%x%n", hex);
/***********输出结果***********/
/*
3.41435936445667E8
101111101011111010111110101111
2fafafaf
7fe9b7aa
*/

下面是合理使用的规则:

  1. 仅限单 _,不能多条相连。
  2. 数值开头和结尾不允许出现 _
  3. FDL的前后禁止出现 _
  4. 二进制前导 b 和 十六进制 x 前后禁止出现 _

指数计数法

// 大写 E 和小写 e 的效果相同:
       float expFloat = 1.39e-43f;
       expFloat = 1.39E-43f;
       System.out.println(expFloat);
       double expDouble = 47e47d; // 'd' 是可选的
       double expDouble2 = 47e47; // 自动转换为 double
       System.out.println(expDouble);
//输出 1.39E-434.7E48

第一行的赋值语句中,因为编译器通常会将指数作为 double 类型来处理,所以假若没有这个后缀字符 f,编译器就会报错,提示我们应该将 double 型转换成 float 型。

位运算符

“与运算符” & :两个输入位都是 1 ,结果才是 1,否则 0

“或运算符” | :至少有一个是 1 ,结果就是 1

“异或运算符” ^ :一个是 1,另一个不是 1 ,结果才是 1

“非运算符” ~ :对1个自变量 取反, 其他所有运算符都是二元运算符)

位运算符和逻辑运算符都使用了同样的字符,只不过数量不同。位短,所以位运算符只有一个字符。位运算符可与等号 = 联合使用以接收结果及赋值:&=|=^= 都是合法的(由于 ~ 是一元运算符,所以不可与 = 联合使用)。

我们将 Boolean 类型被视为“单位值”(one-bit value),所以它多少有些独特的地方。我们可以对 boolean 型变量执行与、或、异或运算,但不能执行非运算(大概是为了避免与逻辑“非”混淆)。对于布尔值,位运算符具有与逻辑运算符相同的效果,只是它们不会中途“短路”。

移位运算符

只能用于处理整数类型。

左移位运算符 << 能将其左边的运算对象向左移动右侧指定的位数(在低位补 0) 。

右移位运算符 >> 则相反。 右移位运算符有“正”、“负”值:若值为正,则在高位插入 0;若值为负,则在高位插入 1。

Java 也添加了一种“不分正负”的右移位运算符(>>>),它使用了“零扩展”(zero extension):无论正负,都在高位插入 0。这一运算符是 C/C++ 没有的。

如果移动 charbyteshort,则会在移动发生之前将其提升为 int,结果为 int。仅使用右值(rvalue)的 5 个低阶位。这可以防止我们移动超过 int 范围的位数。若对一个 long 值进行处理,最后得到的结果也是 long

移位可以与等号 <<=>>=>>>= 组合使用。左值被替换为其移位运算后的值。

三元运算符

三元运算符,也称为条件运算符。与 if-else 不同的是,三元运算符是有返回结果的。

布尔表达式 ? 值 1 : 值 2

若表达式计算为 true,则返回结果 值 1 ;如果表达式的计算为 false,则返回结果 值 2

字符串运算符

运用 String + 时有一些有趣的现象。若表达式以一个 String 类型开头(编译器会自动将双引号 "" 标注的的字符序列转换为字符串),那么后续所有运算对象都必须是字符串。

因为编译器将其分别转换为其字符串形式然后与字符串变量 s 连接。 这种转换与数据的位置无关,只要当中有一条数据是字符串类型,其他非字符串数据都将被转换为字符串形式并连接。 如果需要控制表达式的计算顺序可以使用括号 ()

类型转换 Casting

假设我们为 float 变量赋值一个整数值,计算机会将 int 自动转换成 float

若将数据类型进行“向下转换”(Narrowing Conversion)的操作(将容量较大的数据类型转换成容量较小的类型),可能会发生信息丢失的危险。 “向上转换”(Widening conversion),则不必进行显式的类型转换,因为较大类型的数据肯定能容纳较小类型的数据,不会造成任何信息的丢失。

我们对小于 int 的基本数据类型(即 charbyteshort)执行任何算术或按位操作,这些值会在执行操作之前类型提升为 int,并且结果值的类型为 int。若想重新使用较小的类型,必须使用强制转换(由于重新分配回一个较小的类型,结果可能会丢失精度)。通常,表达式中最大的数据类型是决定表达式结果的数据类型。float 型和 double 型相乘,结果是 double 型的;intlong 相加,结果是 long 型。

截断和舍入

floatdouble 转换为整数值时,小数位将被截断。若你想对结果进行四舍五入,可以使用 java.lang.Mathround() 方法:

相关推荐

阮一峰高质量免费 TypeScript 教程,适合有 JS 基础的人系统学习 TS

好长时间没有分享前端教程了,就在前几天,阮老师发布了历经一年多时间编写的TS教程,第一时间去阅读学习了,也分享给大家。早在“那些免费的砖”这个网站的建站之初,我就向大家推荐了两个JavaScri...

HTML序章(学习目的、对象、基本概念)——零基础自学网页制作

为什么学习网页制作?互联网时代的今天,各种各样的网页充斥着我们的生活。只要使用浏览器,打开的每一个页面都可以称之为网页。即使使用头条这样的APP,其内容布局、展示的方法也脱胎于网页页面设计的方法与原则...

网页内嵌PDF获取的办法(网页内嵌pdf如何下载源文件)

最近女王大人为了通过某认证考试,交了2000RMB,官方居然没有给线下教材资料,直接给的是在线教材,教材是PDF的但是是内嵌在网页内,可惜却没有给具体的PDF地址,无法下载,看到女王大人一点点的截图保...

pdfkit | 利用python实现html文件转pdf

在用jupyternotebook写代码文档的时候,有时需要导出pdf版本,但jupyter会报错。我在想,除了网上的debug方法,还没有其他方案可以生成pdf。度娘搜了下,很多博客推荐Pytho...

在PDF中运行《毁灭战士》:突破文档边界的技术实验

DoomPDF是一个将经典射击游戏《毁灭战士》(Doom)嵌入PDF文件的开源项目。通过巧妙利用PDF格式的隐藏特性,这项实验成功打破了”PDF只能展示静态内容”的固有认知,让用户可以直接在浏览器中...

怎么转换PDF格式文件?这5款免费网站真的好用!

PDF文件是工作学习中的常客,在使用过程中,常常需要对PDF格式进行转换,包括但不限于PDF转Word、PDF转PPT、PDF转图片等等。不过WPS虽然应用广泛,但是里面关于PDF的转换工具必需要会员...

最值得使用的html格式生成PDF工具!

这些工具将任意数量的HTML文件准确的同时保留原来的布局不要求你做任何操作就可以完成。现在互联网用户,网站发布者和博客更新很快,通过内置的工具易于访问HTML内容的PDF文件。保持HTML文本或图像的...

有没有什么方法能将PDF转为HTML呢?PDF转HTML的最佳6个方法

HTML是什么?HTML是超文本标记语言(HyperTextMarkupLanguage),标准通用标记语言下的一个应用。HTML不是一种编程语言,而是一种标记语言(markuplangu...

如何实现将PDF和html相互转换(pdf做成html)

PDF是一种比较稳定的电子文档格式,而HTML则是一种通用的网页格式,如何才能实现这两种格式之间的互转呢?首先将网页转成PDF是相当来说比较简单的操作,而且只要我们对PDF格式比较熟悉,一定都知道PD...

Mac系统中怎么将html网页转成PDF格式?

Mac系统中怎么将html网页转成PDF格式?mac系统中把网页格式的文件想转换成pdf格式的文件,方便打印,该怎么转换呢?下面我们就来看看详细的教程,需要的朋友可以参考下。用途:把网页html转成p...

浏览器中在线预览pdf文件,pdf.mjs插件实现web预览pdf

背景:本来只是淘宝上卖卖袜子,想着扩展一下业务,准备做同名“来家居”海外袜子馆外贸项目,碰到pdf在线预览的需求,就找了pdf.js插件进行实践后把此方法记录下来,可以通过多种方法来实现,每种方法都有...

前端利用Print.js打印base64 PDF(前端利用Print.js打印base64 pdf viewer)

关于Print.jsPrint.js库在https://printjs.crabbly.com/有说细的说明,总体来说其兼容还具有一定的局限性。Print.js项目中的使用我们的打印功能运行在Goog...

ChromiumHtmlToPdf:Net跨平台轻松将HTML转换为PDF

什么是ChromiumHtmlToPdf?ChromiumHtmlToPdf是一个100%纯托管的C#.NETStandard2.0库和.NET8控制台应用程序,也适用于Li...

PDF动画电子书如何制作?(如何制作pdf动图)

PDF无法制作成动画的,但是可以换个思路,把PDF转换为翻页电子书,即可支持动画。这里推荐一款上传PDF转换为翻页电子书的网站:FLBOOK,可以免费上传PDF,转换为可以具有真书翻页特效的电子书,并...

HtmlToPDFCore:HTML 转换为 PDF 的利器,轻便,快捷,重量级

在日常开发中,我们常常需要将动态生成的HTML内容转换为PDF文件。无论是用于打印、存档还是分享,PDF格式都因其跨平台兼容性和稳定性而备受青睐。今天,我们就来介绍一个强大的工具——Htm...